flail 0.0.7 → 0.1.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.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