hydraulic_brake 0.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/.rbenv-version +1 -0
- data/.rvmrc +1 -0
- data/.yardopts +2 -0
- data/Gemfile +16 -0
- data/INSTALL +20 -0
- data/MIT-LICENSE +22 -0
- data/README.md +103 -0
- data/Rakefile +39 -0
- data/VERSION +1 -0
- data/features/rake.feature +27 -0
- data/features/step_definitions/rake_steps.rb +17 -0
- data/features/support/matchers.rb +35 -0
- data/features/support/rake/Rakefile +61 -0
- data/features/support/terminal.rb +107 -0
- data/hydraulic_brake.gemspec +102 -0
- data/lib/hydraulic_brake/backtrace.rb +108 -0
- data/lib/hydraulic_brake/configuration.rb +242 -0
- data/lib/hydraulic_brake/notice.rb +321 -0
- data/lib/hydraulic_brake/sender.rb +128 -0
- data/lib/hydraulic_brake/version.rb +5 -0
- data/lib/hydraulic_brake.rb +148 -0
- data/lib/hydraulic_brake_tasks.rb +63 -0
- data/resources/README.md +34 -0
- data/resources/ca-bundle.crt +3376 -0
- data/script/integration_test.rb +36 -0
- data/test/airbrake_2_3.xsd +88 -0
- data/test/backtrace_test.rb +162 -0
- data/test/configuration_test.rb +178 -0
- data/test/helper.rb +239 -0
- data/test/logger_test.rb +79 -0
- data/test/notice_test.rb +324 -0
- data/test/notifier_test.rb +220 -0
- data/test/recursion_test.rb +10 -0
- data/test/sender_test.rb +288 -0
- metadata +259 -0
data/.rbenv-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3-p194
|
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.3-p194@airbrake --create
|
data/.yardopts
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "builder"
|
4
|
+
|
5
|
+
group "development" do
|
6
|
+
gem "bourne", ">= 1.0"
|
7
|
+
gem "cucumber", "~> 0.10.6"
|
8
|
+
gem "fakeweb", "~> 1.3.0"
|
9
|
+
gem "jeweler"
|
10
|
+
gem "nokogiri", "~> 1.4.3.1"
|
11
|
+
gem "rake"
|
12
|
+
gem "rspec", "~> 2.6.0"
|
13
|
+
gem "shoulda", "~> 2.11.3"
|
14
|
+
gem "simplecov"
|
15
|
+
gem "yard"
|
16
|
+
end
|
data/INSTALL
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
=== Configuration
|
2
|
+
|
3
|
+
You should have something like this in config/initializers/hydraulic_brake.rb.
|
4
|
+
|
5
|
+
HydraulicBrake.configure do |config|
|
6
|
+
config.api_key = '1234567890abcdef'
|
7
|
+
end
|
8
|
+
|
9
|
+
(Please note that this configuration should be in a global configuration, and
|
10
|
+
is *not* environment-specific. HydraulicBrake is smart enough to know what
|
11
|
+
errors are caused by what environments, so your staging errors don't get mixed
|
12
|
+
in with your production errors.)
|
13
|
+
|
14
|
+
You can test that HydraulicBrake is working in your production environment by
|
15
|
+
using this rake task:
|
16
|
+
|
17
|
+
rake hydraulicbrake:test
|
18
|
+
|
19
|
+
If everything is configured properly, that task will send a notice to Airbrake
|
20
|
+
which will be visible immediately.
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2007 - 2012, Exceptional DBA Airbrake.io
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
HydraulicBrake
|
2
|
+
========
|
3
|
+
|
4
|
+
This is a replacement notifier gem for the [Airbrake
|
5
|
+
gem](https://github.com/airbrake/airbrake) which is used
|
6
|
+
for integrating ruby apps with [Airbrake](http://airbrake.io).
|
7
|
+
|
8
|
+
### Transitioning from Airbrake to HydraulicBrake
|
9
|
+
|
10
|
+
HydraulicBrake is a lighter weight alternative to the [Airbrake
|
11
|
+
gem](https://github.com/airbrake/airbrake) and takes a different design
|
12
|
+
approach. HydraulicBrake doesn't attempt to integrate with any
|
13
|
+
frameworks and has few dependencies. HydraulicBrake doesn't change
|
14
|
+
anything outside its own namespace. It doesn't do any automatic
|
15
|
+
exception handling or configuration.
|
16
|
+
|
17
|
+
Configuration
|
18
|
+
-------------
|
19
|
+
|
20
|
+
Configure HydraulicBrake when your app starts with a configuration block
|
21
|
+
like this one:
|
22
|
+
|
23
|
+
HydraulicBrake.configure do |config|
|
24
|
+
config.host = "api.airbrake.io"
|
25
|
+
config.port = "443"
|
26
|
+
config.secure = true
|
27
|
+
config.environment_name = "staging"
|
28
|
+
config.api_key = "<api-key-from-your-airbrake-server>"
|
29
|
+
end
|
30
|
+
|
31
|
+
Usage
|
32
|
+
-----
|
33
|
+
|
34
|
+
Wherever you want to notify an Airbrake server, just call
|
35
|
+
HydraulicBrake#notify
|
36
|
+
|
37
|
+
begin
|
38
|
+
params = {
|
39
|
+
# params that you pass to a method that can throw an exception
|
40
|
+
}
|
41
|
+
my_unpredicable_method(params)
|
42
|
+
rescue => e
|
43
|
+
HydraulicBrake.notify(
|
44
|
+
:error_class => "Special Error",
|
45
|
+
:error_message => "Special Error: #{e.message}",
|
46
|
+
:parameters => params
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
HydraulicBrake merges the hash you pass with these default options:
|
51
|
+
|
52
|
+
{
|
53
|
+
:api_key => HydraulicBrake.api_key,
|
54
|
+
:error_message => 'Notification',
|
55
|
+
:backtrace => caller,
|
56
|
+
:parameters => {},
|
57
|
+
:session => {}
|
58
|
+
}
|
59
|
+
|
60
|
+
You can override any of those parameters.
|
61
|
+
|
62
|
+
Async Notifications
|
63
|
+
-------------------
|
64
|
+
|
65
|
+
HydraulicBrake doesn't provide anything for async notifications, and
|
66
|
+
that's a good thing. Just wrap your calls to Airbrake#notify in the
|
67
|
+
async library of your choice.
|
68
|
+
|
69
|
+
Proxy Support
|
70
|
+
-------------
|
71
|
+
|
72
|
+
The notifier supports using a proxy, if your server is not able to
|
73
|
+
directly reach the Airbrake servers. To configure the proxy settings,
|
74
|
+
added the following information to your HydraulicBrake configuration
|
75
|
+
block.
|
76
|
+
|
77
|
+
HydraulicBrake.configure do |config|
|
78
|
+
config.proxy_host = proxy.host.com
|
79
|
+
config.proxy_port = 4038
|
80
|
+
config.proxy_user = foo # optional
|
81
|
+
config.proxy_pass = bar # optional
|
82
|
+
|
83
|
+
Logging
|
84
|
+
------------
|
85
|
+
|
86
|
+
HydraulicBrake uses STDOUT by default. If you don't like HydraulicBrake
|
87
|
+
scribbling to your standard output, just pass another `Logger` instance
|
88
|
+
inside your configuration:
|
89
|
+
|
90
|
+
HydraulicBrake.configure do |config|
|
91
|
+
...
|
92
|
+
config.logger = Logger.new("path/to/your/log/file")
|
93
|
+
end
|
94
|
+
|
95
|
+
Credits
|
96
|
+
-------
|
97
|
+
|
98
|
+
Thank you to all [the airbrake contributors](https://github.com/airbrake/airbrake/contributors)!
|
99
|
+
|
100
|
+
License
|
101
|
+
-------
|
102
|
+
|
103
|
+
Airbrake is Copyright © 2008-2012 Airbrake. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
gem.name = "hydraulic_brake"
|
17
|
+
gem.homepage = "http://github.com/stevecrozz/hydraulic_brake"
|
18
|
+
gem.license = "MIT"
|
19
|
+
gem.summary = "Simple Airbrake client"
|
20
|
+
gem.description = %Q{Sends notifications to an Airbrake server}
|
21
|
+
gem.email = "stevecrozz@gmail.com"
|
22
|
+
gem.authors = ["Stephen Crosby"]
|
23
|
+
gem.require_paths = ["lib"]
|
24
|
+
end
|
25
|
+
Jeweler::RubygemsDotOrgTasks.new
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
Rake::TestTask.new(:test) do |test|
|
29
|
+
test.libs << 'lib' << 'test'
|
30
|
+
test.pattern = 'test/*_test.rb'
|
31
|
+
test.verbose = true
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'yard'
|
35
|
+
YARD::Rake::YardocTask.new do |t|
|
36
|
+
t.files = ['lib/**/*.rb']
|
37
|
+
end
|
38
|
+
|
39
|
+
task :default => :test
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Feature: Use the Gem to catch errors in a Rake application
|
2
|
+
Background:
|
3
|
+
Given I have built and installed the "airbrake" gem
|
4
|
+
|
5
|
+
Scenario: Catching exceptions in Rake
|
6
|
+
When I run rake with airbrake
|
7
|
+
Then Airbrake should catch the exception
|
8
|
+
|
9
|
+
Scenario: Falling back to default handler before Airbrake is configured
|
10
|
+
When I run rake with airbrake not yet configured
|
11
|
+
Then Airbrake should not catch the exception
|
12
|
+
|
13
|
+
Scenario: Disabling Rake exception catcher
|
14
|
+
When I run rake with airbrake disabled
|
15
|
+
Then Airbrake should not catch the exception
|
16
|
+
|
17
|
+
Scenario: Autodetect, running from terminal
|
18
|
+
When I run rake with airbrake autodetect from terminal
|
19
|
+
Then Airbrake should not catch the exception
|
20
|
+
|
21
|
+
Scenario: Autodetect, not running from terminal
|
22
|
+
When I run rake with airbrake autodetect not from terminal
|
23
|
+
Then Airbrake should catch the exception
|
24
|
+
|
25
|
+
Scenario: Sending the correct component name
|
26
|
+
When I run rake with airbrake
|
27
|
+
Then Airbrake should send the rake command line as the component name
|
@@ -0,0 +1,17 @@
|
|
1
|
+
When /I run rake with (.+)/ do |command|
|
2
|
+
@rake_command = "rake #{command.gsub(' ','_')}"
|
3
|
+
@rake_result = `cd features/support/rake && GEM_HOME=#{BUILT_GEM_ROOT} #{@rake_command} 2>&1`
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /Airbrake should (|not) ?catch the exception/ do |condition|
|
7
|
+
if condition=='not'
|
8
|
+
@rake_result.should_not =~ /^airbrake/
|
9
|
+
else
|
10
|
+
@rake_result.should =~ /^airbrake/
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
Then /Airbrake should send the rake command line as the component name/ do
|
15
|
+
component = @rake_result.match(/^airbrake (.*)$/)[1]
|
16
|
+
component.should == @rake_command
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
RSpec::Matchers.define :have_content do |xpath, content|
|
2
|
+
match do |document|
|
3
|
+
@elements = document.search(xpath)
|
4
|
+
|
5
|
+
if @elements.empty?
|
6
|
+
false
|
7
|
+
else
|
8
|
+
element_with_content = document.at("#{xpath}[contains(.,'#{content}')]")
|
9
|
+
|
10
|
+
if element_with_content.nil?
|
11
|
+
@found = @elements.collect { |element| element.content }
|
12
|
+
|
13
|
+
false
|
14
|
+
else
|
15
|
+
true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
failure_message_for_should do |document|
|
21
|
+
if @elements.empty?
|
22
|
+
"In XML:\n#{document}\nNo element at #{xpath}"
|
23
|
+
else
|
24
|
+
"In XML:\n#{document}\nGot content #{@found.inspect} at #{xpath} instead of #{content.inspect}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
failure_message_for_should_not do |document|
|
29
|
+
unless @elements.empty?
|
30
|
+
"In XML:\n#{document}\nExpcted no content #{content.inspect} at #{xpath}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
World(RSpec::Matchers)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# A test harness for RakeHandler
|
2
|
+
#
|
3
|
+
require 'rake'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'hydraulic_brake'
|
6
|
+
require 'hydraulic_brake/rake_handler'
|
7
|
+
|
8
|
+
HydraulicBrake.configure do |c|
|
9
|
+
end
|
10
|
+
|
11
|
+
# Should catch exception
|
12
|
+
task :hydraulic_brake do
|
13
|
+
HydraulicBrake.configuration.rescue_rake_exceptions = true
|
14
|
+
stub_tty_output(true)
|
15
|
+
raise_exception
|
16
|
+
end
|
17
|
+
|
18
|
+
# Should not catch exception
|
19
|
+
task :hydraulic_brake_disabled do
|
20
|
+
HydraulicBrake.configuration.rescue_rake_exceptions = false
|
21
|
+
stub_tty_output(true)
|
22
|
+
raise_exception
|
23
|
+
end
|
24
|
+
|
25
|
+
# Should not catch exception as tty_output is true
|
26
|
+
task :hydraulic_brake_autodetect_from_terminal do
|
27
|
+
HydraulicBrake.configuration.rescue_rake_exceptions = nil
|
28
|
+
stub_tty_output(true)
|
29
|
+
raise_exception
|
30
|
+
end
|
31
|
+
|
32
|
+
# Should catch exception as tty_output is false
|
33
|
+
task :hydraulic_brake_autodetect_not_from_terminal do
|
34
|
+
HydraulicBrake.configuration.rescue_rake_exceptions = nil
|
35
|
+
stub_tty_output(false)
|
36
|
+
raise_exception
|
37
|
+
end
|
38
|
+
|
39
|
+
task :hydraulic_brake_not_yet_configured do
|
40
|
+
HydraulicBrake.configuration.rescue_rake_exceptions = true
|
41
|
+
stub_tty_output(true)
|
42
|
+
stub_empty_sender
|
43
|
+
raise_exception
|
44
|
+
end
|
45
|
+
|
46
|
+
def stub_empty_sender
|
47
|
+
HydraulicBrake.sender = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def stub_tty_output(value)
|
51
|
+
Rake.application.instance_eval do
|
52
|
+
@tty_output_stub = value
|
53
|
+
def tty_output?
|
54
|
+
@tty_output_stub
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def raise_exception
|
60
|
+
raise 'TEST'
|
61
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
Before do
|
4
|
+
@terminal = Terminal.new
|
5
|
+
end
|
6
|
+
|
7
|
+
After do |story|
|
8
|
+
if story.failed?
|
9
|
+
# puts @terminal.output
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Terminal
|
14
|
+
attr_reader :output, :status
|
15
|
+
attr_accessor :environment_variables, :invoke_heroku_rake_tasks_locally
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@cwd = FileUtils.pwd
|
19
|
+
@output = ""
|
20
|
+
@status = 0
|
21
|
+
@logger = Logger.new(File.join(TEMP_DIR, 'terminal.log'))
|
22
|
+
|
23
|
+
@invoke_heroku_rake_tasks_locally = false
|
24
|
+
|
25
|
+
@environment_variables = {
|
26
|
+
"GEM_HOME" => LOCAL_GEM_ROOT,
|
27
|
+
"GEM_PATH" => "#{LOCAL_GEM_ROOT}:#{BUILT_GEM_ROOT}",
|
28
|
+
"PATH" => "#{gem_bin_path}:#{ENV['PATH']}"
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def cd(directory)
|
33
|
+
@cwd = directory
|
34
|
+
end
|
35
|
+
|
36
|
+
def run(command)
|
37
|
+
command = optionally_invoke_heroku_rake_tasks_locally(command)
|
38
|
+
|
39
|
+
output << "#{command}\n"
|
40
|
+
FileUtils.cd(@cwd) do
|
41
|
+
# The ; forces ruby to shell out so the env settings work right
|
42
|
+
cmdline = "#{environment_settings} #{command} 2>&1 ; "
|
43
|
+
logger.debug(cmdline)
|
44
|
+
result = `#{cmdline}`
|
45
|
+
logger.debug(result)
|
46
|
+
output << result
|
47
|
+
end
|
48
|
+
@status = $?
|
49
|
+
end
|
50
|
+
|
51
|
+
def optionally_invoke_heroku_rake_tasks_locally(command)
|
52
|
+
if invoke_heroku_rake_tasks_locally
|
53
|
+
command.sub(/^heroku /, '')
|
54
|
+
else
|
55
|
+
command
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def echo(string)
|
60
|
+
logger.debug(string)
|
61
|
+
end
|
62
|
+
|
63
|
+
def flush!
|
64
|
+
@output = ""
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_and_install_gem(gemspec)
|
68
|
+
pkg_dir = File.join(TEMP_DIR, 'pkg')
|
69
|
+
FileUtils.mkdir_p(pkg_dir)
|
70
|
+
output = `gem build #{gemspec} 2>&1`
|
71
|
+
gem_file = Dir.glob("*.gem").first
|
72
|
+
unless gem_file
|
73
|
+
raise "Gem didn't build:\n#{output}"
|
74
|
+
end
|
75
|
+
target = File.join(pkg_dir, gem_file)
|
76
|
+
FileUtils.mv(gem_file, target)
|
77
|
+
install_gem_to(LOCAL_GEM_ROOT, target)
|
78
|
+
end
|
79
|
+
|
80
|
+
def install_gem(gem)
|
81
|
+
install_gem_to(LOCAL_GEM_ROOT, gem)
|
82
|
+
end
|
83
|
+
|
84
|
+
def uninstall_gem(gem)
|
85
|
+
`gem uninstall -i #{LOCAL_GEM_ROOT} #{gem}`
|
86
|
+
end
|
87
|
+
|
88
|
+
def prepend_path(path)
|
89
|
+
@environment_variables['PATH'] = path + ":" + @environment_variables['PATH']
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def install_gem_to(root, gem)
|
95
|
+
`gem install -i #{root} --no-ri --no-rdoc #{gem}`
|
96
|
+
end
|
97
|
+
|
98
|
+
def environment_settings
|
99
|
+
@environment_variables.map { |key, value| "#{key}=#{value}" }.join(' ')
|
100
|
+
end
|
101
|
+
|
102
|
+
def gem_bin_path
|
103
|
+
File.join(LOCAL_GEM_ROOT, "bin")
|
104
|
+
end
|
105
|
+
|
106
|
+
attr_reader :logger
|
107
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "hydraulic_brake"
|
8
|
+
s.version = "0.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Stephen Crosby"]
|
12
|
+
s.date = "2013-07-14"
|
13
|
+
s.description = "Sends notifications to an Airbrake server"
|
14
|
+
s.email = "stevecrozz@gmail.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.md"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".rbenv-version",
|
20
|
+
".rvmrc",
|
21
|
+
".yardopts",
|
22
|
+
"Gemfile",
|
23
|
+
"INSTALL",
|
24
|
+
"MIT-LICENSE",
|
25
|
+
"README.md",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"features/rake.feature",
|
29
|
+
"features/step_definitions/rake_steps.rb",
|
30
|
+
"features/support/matchers.rb",
|
31
|
+
"features/support/rake/Rakefile",
|
32
|
+
"features/support/terminal.rb",
|
33
|
+
"hydraulic_brake.gemspec",
|
34
|
+
"lib/hydraulic_brake.rb",
|
35
|
+
"lib/hydraulic_brake/backtrace.rb",
|
36
|
+
"lib/hydraulic_brake/configuration.rb",
|
37
|
+
"lib/hydraulic_brake/notice.rb",
|
38
|
+
"lib/hydraulic_brake/sender.rb",
|
39
|
+
"lib/hydraulic_brake/version.rb",
|
40
|
+
"lib/hydraulic_brake_tasks.rb",
|
41
|
+
"resources/README.md",
|
42
|
+
"resources/ca-bundle.crt",
|
43
|
+
"script/integration_test.rb",
|
44
|
+
"test/airbrake_2_3.xsd",
|
45
|
+
"test/backtrace_test.rb",
|
46
|
+
"test/configuration_test.rb",
|
47
|
+
"test/helper.rb",
|
48
|
+
"test/logger_test.rb",
|
49
|
+
"test/notice_test.rb",
|
50
|
+
"test/notifier_test.rb",
|
51
|
+
"test/recursion_test.rb",
|
52
|
+
"test/sender_test.rb"
|
53
|
+
]
|
54
|
+
s.homepage = "http://github.com/stevecrozz/hydraulic_brake"
|
55
|
+
s.licenses = ["MIT"]
|
56
|
+
s.require_paths = ["lib"]
|
57
|
+
s.rubygems_version = "1.8.23"
|
58
|
+
s.summary = "Simple Airbrake client"
|
59
|
+
|
60
|
+
if s.respond_to? :specification_version then
|
61
|
+
s.specification_version = 3
|
62
|
+
|
63
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
64
|
+
s.add_runtime_dependency(%q<builder>, [">= 0"])
|
65
|
+
s.add_development_dependency(%q<bourne>, [">= 1.0"])
|
66
|
+
s.add_development_dependency(%q<cucumber>, ["~> 0.10.6"])
|
67
|
+
s.add_development_dependency(%q<fakeweb>, ["~> 1.3.0"])
|
68
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
69
|
+
s.add_development_dependency(%q<nokogiri>, ["~> 1.4.3.1"])
|
70
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
71
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
|
72
|
+
s.add_development_dependency(%q<shoulda>, ["~> 2.11.3"])
|
73
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
74
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
75
|
+
else
|
76
|
+
s.add_dependency(%q<builder>, [">= 0"])
|
77
|
+
s.add_dependency(%q<bourne>, [">= 1.0"])
|
78
|
+
s.add_dependency(%q<cucumber>, ["~> 0.10.6"])
|
79
|
+
s.add_dependency(%q<fakeweb>, ["~> 1.3.0"])
|
80
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
81
|
+
s.add_dependency(%q<nokogiri>, ["~> 1.4.3.1"])
|
82
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
83
|
+
s.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
84
|
+
s.add_dependency(%q<shoulda>, ["~> 2.11.3"])
|
85
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
86
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
87
|
+
end
|
88
|
+
else
|
89
|
+
s.add_dependency(%q<builder>, [">= 0"])
|
90
|
+
s.add_dependency(%q<bourne>, [">= 1.0"])
|
91
|
+
s.add_dependency(%q<cucumber>, ["~> 0.10.6"])
|
92
|
+
s.add_dependency(%q<fakeweb>, ["~> 1.3.0"])
|
93
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
94
|
+
s.add_dependency(%q<nokogiri>, ["~> 1.4.3.1"])
|
95
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
96
|
+
s.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
97
|
+
s.add_dependency(%q<shoulda>, ["~> 2.11.3"])
|
98
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
99
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module HydraulicBrake
|
2
|
+
# Front end to parsing the backtrace for each notice
|
3
|
+
class Backtrace
|
4
|
+
|
5
|
+
# Handles backtrace parsing line by line
|
6
|
+
class Line
|
7
|
+
|
8
|
+
# regexp (optionnally allowing leading X: for windows support)
|
9
|
+
INPUT_FORMAT = %r{^((?:[a-zA-Z]:)?[^:]+):(\d+)(?::in `([^']+)')?$}.freeze
|
10
|
+
|
11
|
+
# The file portion of the line (such as app/models/user.rb)
|
12
|
+
attr_reader :file
|
13
|
+
|
14
|
+
# The line number portion of the line
|
15
|
+
attr_reader :number
|
16
|
+
|
17
|
+
# The method of the line (such as index)
|
18
|
+
attr_reader :method
|
19
|
+
|
20
|
+
# Parses a single line of a given backtrace
|
21
|
+
# @param [String] unparsed_line The raw line from +caller+ or some backtrace
|
22
|
+
# @return [Line] The parsed backtrace line
|
23
|
+
def self.parse(unparsed_line)
|
24
|
+
_, file, number, method = unparsed_line.match(INPUT_FORMAT).to_a
|
25
|
+
new(file, number, method)
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(file, number, method)
|
29
|
+
self.file = file
|
30
|
+
self.number = number
|
31
|
+
self.method = method
|
32
|
+
end
|
33
|
+
|
34
|
+
# Reconstructs the line in a readable fashion
|
35
|
+
def to_s
|
36
|
+
"#{file}:#{number}:in `#{method}'"
|
37
|
+
end
|
38
|
+
|
39
|
+
def ==(other)
|
40
|
+
to_s == other.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
def inspect
|
44
|
+
"<Line:#{to_s}>"
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
attr_writer :file, :number, :method
|
50
|
+
end
|
51
|
+
|
52
|
+
# holder for an Array of Backtrace::Line instances
|
53
|
+
attr_reader :lines
|
54
|
+
|
55
|
+
def self.parse(ruby_backtrace, opts = {})
|
56
|
+
ruby_lines = split_multiline_backtrace(ruby_backtrace)
|
57
|
+
|
58
|
+
filters = opts[:filters] || []
|
59
|
+
filtered_lines = ruby_lines.to_a.map do |line|
|
60
|
+
filters.inject(line) do |line, proc|
|
61
|
+
proc.call(line)
|
62
|
+
end
|
63
|
+
end.compact
|
64
|
+
|
65
|
+
lines = filtered_lines.collect do |unparsed_line|
|
66
|
+
Line.parse(unparsed_line)
|
67
|
+
end
|
68
|
+
|
69
|
+
instance = new(lines)
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize(lines)
|
73
|
+
self.lines = lines
|
74
|
+
end
|
75
|
+
|
76
|
+
def inspect
|
77
|
+
"<Backtrace: " + lines.collect { |line| line.inspect }.join(", ") + ">"
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_s
|
81
|
+
content = []
|
82
|
+
lines.each do |line|
|
83
|
+
content << line
|
84
|
+
end
|
85
|
+
content.join("\n")
|
86
|
+
end
|
87
|
+
|
88
|
+
def ==(other)
|
89
|
+
if other.respond_to?(:lines)
|
90
|
+
lines == other.lines
|
91
|
+
else
|
92
|
+
false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
attr_writer :lines
|
99
|
+
|
100
|
+
def self.split_multiline_backtrace(backtrace)
|
101
|
+
if backtrace.to_a.size == 1
|
102
|
+
backtrace.to_a.first.split(/\n\s*/)
|
103
|
+
else
|
104
|
+
backtrace
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|