flail 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- flail (0.0.6)
4
+ flail (0.0.7)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -0,0 +1,122 @@
1
+ class Flail
2
+ # Front end to parsing the backtrace for each notice
3
+ class Backtrace
4
+
5
+ DEFAULT_FILTERS = [
6
+ lambda { |line| line.gsub(/^\.\//, "") },
7
+ lambda { |line|
8
+ if defined?(Gem)
9
+ Gem.path.inject(line) do |line, path|
10
+ line.gsub(/#{path}/, "[GEM_ROOT]")
11
+ end
12
+ end
13
+ },
14
+ lambda { |line| line if line !~ %r{lib/flail} }
15
+ ].freeze
16
+
17
+ # Handles backtrace parsing line by line
18
+ class Line
19
+
20
+ # regexp (optionnally allowing leading X: for windows support)
21
+ INPUT_FORMAT = %r{^((?:[a-zA-Z]:)?[^:]+):(\d+)(?::in `([^']+)')?$}.freeze # `
22
+
23
+ # The file portion of the line (such as app/models/user.rb)
24
+ attr_reader :file
25
+
26
+ # The line number portion of the line
27
+ attr_reader :number
28
+
29
+ # The method of the line (such as index)
30
+ attr_reader :method
31
+
32
+ # Parses a single line of a given backtrace
33
+ # @param [String] unparsed_line The raw line from +caller+ or some backtrace
34
+ # @return [Line] The parsed backtrace line
35
+ def self.parse(unparsed_line)
36
+ _, file, number, method = unparsed_line.match(INPUT_FORMAT).to_a
37
+ new(file, number, method)
38
+ end
39
+
40
+ def initialize(file, number, method)
41
+ self.file = file
42
+ self.number = number
43
+ self.method = method
44
+ end
45
+
46
+ # Reconstructs the line in a readable fashion
47
+ def to_s
48
+ "#{file}:#{number}:in `#{method}'"
49
+ end
50
+
51
+ def ==(other)
52
+ to_s == other.to_s
53
+ end
54
+
55
+ def inspect
56
+ "<Line:#{to_s}>"
57
+ end
58
+
59
+ private
60
+
61
+ attr_writer :file, :number, :method
62
+ end
63
+
64
+ # holder for an Array of Backtrace::Line instances
65
+ attr_reader :lines
66
+
67
+ def self.parse(ruby_backtrace, opts = {})
68
+ ruby_lines = split_multiline_backtrace(ruby_backtrace)
69
+
70
+ filters = opts[:filters] || []
71
+ filtered_lines = ruby_lines.to_a.map do |line|
72
+ filters.inject(line) do |line, proc|
73
+ proc.call(line)
74
+ end
75
+ end.compact
76
+
77
+ lines = filtered_lines.collect do |unparsed_line|
78
+ Line.parse(unparsed_line)
79
+ end
80
+
81
+ instance = new(lines)
82
+ end
83
+
84
+ def initialize(lines)
85
+ self.lines = lines
86
+ end
87
+
88
+ def inspect
89
+ "<Backtrace: " + lines.collect { |line| line.inspect }.join(", ") + ">"
90
+ end
91
+
92
+ def ==(other)
93
+ if other.respond_to?(:lines)
94
+ lines == other.lines
95
+ else
96
+ false
97
+ end
98
+ end
99
+
100
+ def to_ary
101
+ lines.inject([]) do |collector, line|
102
+ collector << {
103
+ :number => line.number,
104
+ :file => line.file,
105
+ :method => line.method
106
+ }
107
+ end
108
+ end
109
+
110
+ private
111
+
112
+ attr_writer :lines
113
+
114
+ def self.split_multiline_backtrace(backtrace)
115
+ if backtrace.to_a.size == 1
116
+ backtrace.to_a.first.split(/\n\s*/)
117
+ else
118
+ backtrace
119
+ end
120
+ end
121
+ end
122
+ end
@@ -42,12 +42,26 @@ class Flail
42
42
  clean_unserializable_data(value, stack + [data.object_id])
43
43
  end
44
44
  else
45
- data.to_s
45
+ input = if ''.respond_to?(:encode)
46
+ data.to_s.encode(Encoding::UTF_8, :undef => :replace)
47
+ else
48
+ require 'iconv'
49
+ ic = Iconv.new("UTF-8//IGNORE", "UTF-8")
50
+ ic.iconv(data.to_s + ' ')[0..-2]
51
+ end
52
+ begin
53
+ input.to_json
54
+ rescue Exception => e
55
+ input = "redundant utf-8 sequence"
56
+ end
57
+
58
+ input
46
59
  end
47
60
  end
48
61
 
49
62
  def clean_rack_env(data)
50
63
  data.delete("rack.request.form_vars")
64
+ data.delete("rack.input")
51
65
  data
52
66
  end
53
67
 
@@ -64,16 +78,18 @@ class Flail
64
78
  info = {}
65
79
 
66
80
  # rack env
67
- info[:rack] = clean_rack_env(clean_unserializable_data(@env))
81
+ info[:rack] = clean_unserializable_data(clean_rack_env(@env))
68
82
 
69
- info[:class_name] = @exception.class.to_s # @exception class
83
+ info[:class_name] = @exception.class.name # @exception class
70
84
  info[:message] = @exception.to_s # error message
71
- info[:trace] = @exception.backtrace # backtrace of error
72
85
  info[:target_url] = request_data[:target_url] # url of request
73
86
  info[:referer_url] = request_data[:referer_url] # referer
74
87
  info[:user_agent] = request_data[:user_agent] # user agent
75
88
  info[:user] = request_data[:user] # current user
76
89
 
90
+ # backtrace of error
91
+ info[:trace] = Flail::Backtrace.parse(@exception.backtrace, :filters => Flail::Backtrace::DEFAULT_FILTERS).to_ary
92
+
77
93
  # request parameters
78
94
  info[:parameters] = clean_unserializable_data(request_data[:parameters])
79
95
 
@@ -83,7 +99,7 @@ class Flail
83
99
  # special variables
84
100
  info[:environment] = Flail.configuration.env
85
101
  info[:hostname] = Flail.configuration.hostname
86
- info[:tag] = Flail.configuration.tag
102
+ info[:tag] = Flail.configuration.tag
87
103
 
88
104
  info
89
105
  end
data/lib/flail/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Flail
2
- VERSION = "0.0.7"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/flail.rb CHANGED
@@ -4,6 +4,7 @@ require 'socket'
4
4
 
5
5
  require 'flail/base'
6
6
  require 'flail/configuration'
7
+ require 'flail/backtrace'
7
8
  require 'flail/exception'
8
9
  require 'flail/rack'
9
10
 
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ require 'flail/backtrace'
4
+
5
+ describe Flail::Backtrace do
6
+
7
+ SAMPLE_BACKTRACE = [
8
+ "app/models/user.rb:13:in `magic'",
9
+ "app/controllers/users_controller.rb:8:in `index'"
10
+ ]
11
+
12
+
13
+ it "should parse a backtrace into lines" do
14
+ backtrace = Flail::Backtrace.parse(SAMPLE_BACKTRACE)
15
+
16
+ line = backtrace.lines.first
17
+ line.number.should == '13'
18
+ line.file.should == 'app/models/user.rb'
19
+ line.method.should == 'magic'
20
+
21
+ line = backtrace.lines.last
22
+ line.number.should == '8'
23
+ line.file.should == 'app/controllers/users_controller.rb'
24
+ line.method.should == 'index'
25
+ end
26
+
27
+
28
+ it "should parse a windows backtrace into lines" do
29
+ array = [
30
+ "C:/Program Files/Server/app/models/user.rb:13:in `magic'",
31
+ "C:/Program Files/Server/app/controllers/users_controller.rb:8:in `index'"
32
+ ]
33
+
34
+ backtrace = Flail::Backtrace.parse(array)
35
+
36
+ line = backtrace.lines.first
37
+ line.number.should == '13'
38
+ line.file.should == 'C:/Program Files/Server/app/models/user.rb'
39
+ line.method.should == 'magic'
40
+
41
+ line = backtrace.lines.last
42
+ line.number.should == '8'
43
+ line.file.should == 'C:/Program Files/Server/app/controllers/users_controller.rb'
44
+ line.method.should == 'index'
45
+ end
46
+
47
+ it "should be equal with equal lines" do
48
+ one = SAMPLE_BACKTRACE
49
+ two = one.dup
50
+
51
+ Flail::Backtrace.parse(one).should == Flail::Backtrace.parse(two)
52
+ end
53
+
54
+ it "should parse massive one-line exceptions into multiple lines" do
55
+ original_backtrace = Flail::Backtrace.parse(["one:1:in `one'\n two:2:in `two'\n three:3:in `three`"])
56
+ expected_backtrace = Flail::Backtrace.parse(["one:1:in `one'", "two:2:in `two'", "three:3:in `three`"])
57
+
58
+ expected_backtrace.should == original_backtrace
59
+ end
60
+
61
+ it "should remove notifier trace" do
62
+ inside_notifier = ['lib/flail/exception.rb:13:in `voodoo`']
63
+ outside_notifier = ['users_controller:8:in `index`']
64
+
65
+ without_inside = Flail::Backtrace.parse(outside_notifier)
66
+ with_inside = Flail::Backtrace.parse(inside_notifier + outside_notifier,
67
+ :filters => Flail::Backtrace::DEFAULT_FILTERS)
68
+
69
+ without_inside.should == with_inside
70
+ end
71
+
72
+ it "should run filters on the backtrace" do
73
+ filters = [lambda { |line| line.sub('foo', 'bar') }]
74
+
75
+ input = Flail::Backtrace.parse(["foo:13:in `one'",
76
+ "baz:14:in `two'"
77
+ ], :filters => filters)
78
+
79
+ expected = Flail::Backtrace.parse(["bar:13:in `one'",
80
+ "baz:14:in `two'"
81
+ ])
82
+
83
+ expected.should == input
84
+ end
85
+ end
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ require 'ostruct'
5
+ require 'flail/backtrace'
6
+ require 'flail/exception'
7
+
8
+ describe Flail::Exception do
9
+
10
+ subject { Flail::Exception.new({}, Exception.new) }
11
+ SAMPLE_BACKTRACE = [
12
+ "app/models/user.rb:13:in `magic'",
13
+ "app/controllers/users_controller.rb:8:in `index'"
14
+ ]
15
+
16
+ it "should not choke on bad utf-8" do
17
+ b1r = 0xc0..0xc2
18
+ b2r = 0x80..0xbf
19
+ b1r.each do |b1|
20
+ b2r.each do |b2|
21
+ string = [b1,b2].pack("C*")
22
+
23
+ lambda { subject.clean_unserializable_data({:test => string}).to_json }.should_not raise_error
24
+ end
25
+ end
26
+ end
27
+ end
@@ -49,5 +49,39 @@ describe Flail::Rails::RescueAction do
49
49
 
50
50
  FlailArmory.payload['user'].should == {'id' => 1, 'login' => 'jlong'}
51
51
  end
52
+
53
+ it "should call session.to_hash if available" do
54
+ hash_data = {:key => :value}
55
+
56
+ session = ActionController::TestSession.new
57
+ stub(ActionController::TestSession).new { session }
58
+ stub(session).to_hash { hash_data }
59
+
60
+ FlailArmory.process_action_with_error
61
+
62
+ session.should have_received.to_hash
63
+ session.should_not have_received.data
64
+ FlailArmory.payload.should_not be_nil
65
+ end
66
+
67
+ it "should call session.to_hash if available" do
68
+ hash_data = {:key => :value}
69
+
70
+ session = ActionController::TestSession.new
71
+ stub(ActionController::TestSession).new { session }
72
+ stub(session).data { hash_data }
73
+
74
+ if session.respond_to?(:to_hash)
75
+ class << session
76
+ undef :to_hash
77
+ end
78
+ end
79
+
80
+ FlailArmory.process_action_with_error
81
+
82
+ session.should_not have_received.to_hash
83
+ session.should have_received.data
84
+ FlailArmory.payload.should_not be_nil
85
+ end
52
86
  end
53
87
  end
data/spec/spec_helper.rb CHANGED
@@ -20,6 +20,9 @@ require 'flail'
20
20
  require 'flail/rails/controller_methods'
21
21
  require 'flail/rails/rescue_action'
22
22
 
23
+
24
+ Dir["#{File.expand_path(File.dirname(__FILE__))}/support/*.rb"].map {|file| require(file)}
25
+
23
26
  class FlailArmory
24
27
 
25
28
  module ClassMethods
@@ -0,0 +1,42 @@
1
+ # --- add this as spec/support/rr.rb ---
2
+
3
+ # RR doesn't have support for RSpec 2.
4
+ #
5
+ # Source: <https://github.com/btakita/rr/issues#issue/45>
6
+
7
+ require 'rr'
8
+
9
+ module RR
10
+ module Adapters
11
+ module RSpec2
12
+ include RRMethods
13
+
14
+ def setup_mocks_for_rspec
15
+ RR.reset
16
+ end
17
+ def verify_mocks_for_rspec
18
+ RR.verify
19
+ end
20
+ def teardown_mocks_for_rspec
21
+ RR.reset
22
+ end
23
+
24
+ def have_received(method = nil)
25
+ RR::Adapters::Rspec::InvocationMatcher.new(method)
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ module RSpec
32
+ module Core
33
+ module MockFrameworkAdapter
34
+ include RR::Adapters::RSpec2
35
+ end
36
+ end
37
+ end
38
+
39
+ RSpec.configure do |config|
40
+ config.mock_framework = RSpec::Core::MockFrameworkAdapter
41
+ config.backtrace_clean_patterns.push(RR::Errors::BACKTRACE_IDENTIFIER)
42
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-09 00:00:00.000000000 Z
12
+ date: 2012-08-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -157,6 +157,7 @@ files:
157
157
  - Rakefile
158
158
  - flail.gemspec
159
159
  - lib/flail.rb
160
+ - lib/flail/backtrace.rb
160
161
  - lib/flail/base.rb
161
162
  - lib/flail/configuration.rb
162
163
  - lib/flail/exception.rb
@@ -168,9 +169,12 @@ files:
168
169
  - lib/flail/railtie.rb
169
170
  - lib/flail/version.rb
170
171
  - rails/init.rb
172
+ - spec/backtrace_spec.rb
171
173
  - spec/base_spec.rb
174
+ - spec/exception_spec.rb
172
175
  - spec/rescue_action_spec.rb
173
176
  - spec/spec_helper.rb
177
+ - spec/support/rr.rb
174
178
  homepage: https://github.com/asceth/flail
175
179
  licenses: []
176
180
  post_install_message:
@@ -196,6 +200,9 @@ signing_key:
196
200
  specification_version: 3
197
201
  summary: Rails exception handler
198
202
  test_files:
203
+ - spec/backtrace_spec.rb
199
204
  - spec/base_spec.rb
205
+ - spec/exception_spec.rb
200
206
  - spec/rescue_action_spec.rb
201
207
  - spec/spec_helper.rb
208
+ - spec/support/rr.rb