temescal 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2d87fe04c5479ea7fc4081a5c20c1e00ecab56f7
4
- data.tar.gz: 311bdc3696f87f883d63b77924f05a1d9c448518
3
+ metadata.gz: 703ee645d282ae0d060ee10a7c86f8e244abf307
4
+ data.tar.gz: 709b6344067afe53bd9bc0c0094c9931fb597d78
5
5
  SHA512:
6
- metadata.gz: f478224b88e7cd8ca0bd5ecf9119c5593856c3c355a808953a0837ddd5f978c7a0e7529ec491306913e9365063095f2d3554f116c3cb3c099af31817606c7437
7
- data.tar.gz: f713acaf1042b6864275125bfcdd01c2bb448a33119248b8ff9e548d978a5ce92f6e9e2a3bdc862b7b7e6f71c4ee81f0e3cb913dc4a97bac5e95c6820ca71475
6
+ metadata.gz: c7adcffdc5f34d2e77da605d45ad237cdd7ee61ac5d8d382247b204223306ba8b461b2ccd0995ad1b3b06f485a81b870a6135303100e60f9d005965a25578b0e
7
+ data.tar.gz: 5d7e7cbc05af0e2f2b2c81c12a6839e1c375dc59ff77742b8cf949a42963bef0cbbf8b0840f246c6634ec3bf168991e804601331e4254a74df336c19ecaab4b0
data/README.md CHANGED
@@ -49,5 +49,7 @@ Temescal provides several configuration options for you. You can set these optio
49
49
 
50
50
  `default_message` to set an all-encompasing message to use in responses instead of the exception's message. Takes a string.
51
51
 
52
+ `ignored_errors` to set which exception types you'd like to not be reported to a monitor or logged. Specified errors will still have error responses built, but they won't trigger any sort of logging. It takes the class names of the exceptions you'd like ignored.
53
+
52
54
  ## License
53
55
  Copyright 2013-2014 Todd Bealmear. See LICENSE for details.
data/lib/temescal.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  module Temescal
2
2
  require 'temescal/configuration'
3
+ require 'temescal/error'
3
4
  require 'temescal/middleware'
4
5
  require 'temescal/monitors'
5
6
  require 'temescal/response'
@@ -4,6 +4,9 @@ module Temescal
4
4
  # Public: Getter for monitors array.
5
5
  attr_reader :monitors
6
6
 
7
+ # Public: Getter for ignored errors array.
8
+ attr_reader :ignored_errors
9
+
7
10
  # Public: Setter for raise_errors option.
8
11
  attr_writer :raise_errors
9
12
 
@@ -15,6 +18,7 @@ module Temescal
15
18
  # Returns a new Configuration object.
16
19
  def initialize
17
20
  @monitors = []
21
+ @ignored_errors = []
18
22
  end
19
23
 
20
24
  # Public: Setter for monitors option.
@@ -42,6 +46,13 @@ module Temescal
42
46
  @raise_errors == true || ENV["RACK_ENV"] == "test"
43
47
  end
44
48
 
49
+ # Public: Setter for ignored_errors option.
50
+ #
51
+ # errors - Zero or more Exception classes.
52
+ def ignored_errors=(*errors)
53
+ @ignored_errors = errors.flatten
54
+ end
55
+
45
56
  private
46
57
 
47
58
  # Private: Converts a snake cased Symbol to a camel cased String.
@@ -0,0 +1,68 @@
1
+ module Temescal
2
+ class Error
3
+ NOT_FOUND_ERRORS = ["ActiveRecord::RecordNotFound", "Sinatra::NotFound"]
4
+
5
+ # Public: Instantiates a new Error.
6
+ #
7
+ # exception - The raw exception being rescued.
8
+ #
9
+ # Returns a new Error.
10
+ def initialize(exception)
11
+ @exception = exception
12
+ end
13
+
14
+ # Public: Determines whether to use a default message (as specified in the
15
+ # configuration) or the exception's message for the API response.
16
+ #
17
+ # Returns a String that's either the default message or the exception's
18
+ # message.
19
+ def message
20
+ configuration.default_message || @exception.message
21
+ end
22
+
23
+ # Public: Determines the proper error code for the exception.
24
+ #
25
+ # Returns a Fixnum based on the exception's type and http_status
26
+ # attribute (if applicable), will return a generic 500 for all others.
27
+ def status
28
+ return 404 if NOT_FOUND_ERRORS.include? @exception.class.to_s
29
+ @exception.respond_to?(:http_status) ? @exception.http_status : 500
30
+ end
31
+
32
+ # Public: Formats the exception for logging.
33
+ #
34
+ # Returns a String containing the relevant exception information to log
35
+ # via STDERR.
36
+ def formatted
37
+ message = "\n#{@exception.class}: #{@exception.message}\n "
38
+ message << @exception.backtrace.join("\n ")
39
+ message << "\n\n"
40
+ end
41
+
42
+ # Public: Gets the exception's type.
43
+ #
44
+ # Returns a String representing the exception class name.
45
+ def type
46
+ @exception.class.to_s
47
+ end
48
+
49
+ # Public: Determines whether an exception should be silenced.
50
+ #
51
+ # Returns true if the error type is configured as an ignored error, false
52
+ # otherwise.
53
+ def ignore?
54
+ configuration.ignored_errors.each do |error|
55
+ return true if @exception.is_a? error
56
+ end
57
+
58
+ false
59
+ end
60
+
61
+ private
62
+
63
+ # Private: Getter for Temescal configuration.
64
+ def configuration
65
+ $_temescal_configuration
66
+ end
67
+ end
68
+ end
@@ -1,7 +1,5 @@
1
1
  module Temescal
2
2
  class Middleware
3
- NOT_FOUND_ERRORS = ["ActiveRecord::RecordNotFound", "Sinatra::NotFound"]
4
-
5
3
  # Public: Initializes the middleware.
6
4
  #
7
5
  # app - The Rack application.
@@ -23,40 +21,28 @@ module Temescal
23
21
  def call(env)
24
22
  begin
25
23
  @status, @headers, @response = @app.call(env)
26
- rescue => error
24
+ rescue => exception
27
25
  raise if configuration.raise_errors?
28
26
 
29
- @error = error
30
- message = configuration.default_message || @error.message
27
+ error = Error.new(exception)
31
28
 
32
- $stderr.print formatted_error
33
- configuration.monitors.each { |monitor| monitor.report(@error) }
29
+ unless error.ignore?
30
+ $stderr.print error.formatted
31
+ configuration.monitors.each { |monitor| monitor.report(exception) }
32
+ end
34
33
 
35
- @status = set_status
36
- @response = Response.build(@status, @error, message)
37
- @headers = { "Content-Type" => "application/json" }
34
+ @status = error.status
35
+ @response = Response.build(error)
36
+ @headers = { "Content-Type" => "application/json" }
38
37
  end
39
38
  [@status, @headers, @response]
40
39
  end
41
40
 
42
41
  private
43
42
 
44
- # Private: Getter for middleware configuration.
43
+ # Private: Getter for Temescal configuration.
45
44
  def configuration
46
- @_configuration ||= Configuration.new
47
- end
48
-
49
- # Private: Formats the exception for logging.
50
- def formatted_error
51
- message = "\n#{@error.class}: #{@error.message}\n "
52
- message << @error.backtrace.join("\n ")
53
- message << "\n\n"
54
- end
55
-
56
- # Private: Returns the proper error code for the exception.
57
- def set_status
58
- return 404 if NOT_FOUND_ERRORS.include? @error.class.to_s
59
- @error.respond_to?(:http_status) ? @error.http_status : 500
45
+ $_temescal_configuration ||= Configuration.new
60
46
  end
61
47
  end
62
48
  end
@@ -5,18 +5,16 @@ module Temescal
5
5
 
6
6
  # Public: Builds a response body for the Rack response.
7
7
  #
8
- # status - The HTTP status code of the response.
9
- # exception - The caught exception.
10
- # message - The error message.
8
+ # error - The Temescal::Error object representing the caught exception.
11
9
  #
12
10
  # Returns an Array containing a JSON string as the response body.
13
- def self.build(status, exception, message)
11
+ def self.build(error)
14
12
  [
15
13
  {
16
14
  meta: {
17
- status: status,
18
- error: exception.class.to_s,
19
- message: message
15
+ status: error.status,
16
+ error: error.type,
17
+ message: error.message
20
18
  }
21
19
  }.to_json
22
20
  ]
@@ -1,3 +1,3 @@
1
1
  module Temescal
2
- VERSION = '0.1.1'
2
+ VERSION = '0.1.2'
3
3
  end
@@ -0,0 +1,79 @@
1
+ require "spec_helper"
2
+
3
+ describe Temescal::Error do
4
+ let(:exception) { StandardError.new("Foobar") }
5
+ let(:error) { Temescal::Error.new(exception) }
6
+
7
+ before do
8
+ # This is admittedly a little hacky, but it's the best way to prevent
9
+ # previously memoized configurations from polluting these tests.
10
+ $_temescal_configuration = Temescal::Configuration.new
11
+ end
12
+
13
+ context "#message" do
14
+ it "should return the configured default message if it is set in the configuration" do
15
+ Temescal::Configuration.any_instance.stub(:default_message).and_return("Some other message.")
16
+
17
+ expect(error.message).to eq "Some other message."
18
+ end
19
+
20
+ it "should return the exception's message if the default message is not configured" do
21
+ expect(error.message).to eq "Foobar"
22
+ end
23
+ end
24
+
25
+ context "#status" do
26
+ it "should return 404 if the exception is an ActiveRecord::RecordNotFound" do
27
+ exception = ActiveRecord::RecordNotFound.new
28
+ error = Temescal::Error.new(exception)
29
+
30
+ expect(error.status).to eq 404
31
+ end
32
+
33
+ it "should return 404 if the exception is a Sinatra::NotFound" do
34
+ exception = Sinatra::NotFound.new
35
+ error = Temescal::Error.new(exception)
36
+
37
+ expect(error.status).to eq 404
38
+ end
39
+
40
+ it "should return the exception's status code if assigned" do
41
+ exception.stub(:http_status).and_return(403)
42
+
43
+ expect(error.status).to eq 403
44
+ end
45
+
46
+ it "should return 500 for all other exceptions" do
47
+ expect(error.status).to eq 500
48
+ end
49
+ end
50
+
51
+ context "#formatted" do
52
+ it "should return a String formatted for log output" do
53
+ exception.stub(:backtrace).and_return(["Line 1", "Line 2"])
54
+
55
+ expect(error.formatted).to eq "\nStandardError: Foobar\n Line 1\n Line 2\n\n"
56
+ end
57
+ end
58
+
59
+ context "#type" do
60
+ it "should return the exception's class name" do
61
+ expect(error.type).to eq "StandardError"
62
+ end
63
+ end
64
+
65
+ context "#ignore?" do
66
+ before do
67
+ Temescal::Configuration.any_instance.stub(:ignored_errors).and_return([TypeError])
68
+ end
69
+
70
+ it "should return true if the exception type is configured as an ignored error" do
71
+ error = Temescal::Error.new(TypeError.new)
72
+ expect(error.ignore?).to be_true
73
+ end
74
+
75
+ it "should return false if the exception type is not an ignored error" do
76
+ expect(error.ignore?).to be_false
77
+ end
78
+ end
79
+ end
@@ -1,9 +1,10 @@
1
1
  require "spec_helper"
2
2
 
3
- require "active_record"
4
- require "sinatra"
5
-
6
3
  describe Temescal::Middleware do
4
+ before do
5
+ $_temescal_configuration = nil
6
+ end
7
+
7
8
  context "Ok response" do
8
9
  let(:app) { ->(env) { [200, env, "app" ] } }
9
10
 
@@ -33,6 +34,7 @@ describe Temescal::Middleware do
33
34
  let(:middleware) do
34
35
  Temescal::Middleware.new(app) do |config|
35
36
  config.monitors = :new_relic
37
+ config.ignored_errors = TypeError
36
38
  end
37
39
  end
38
40
 
@@ -111,6 +113,27 @@ describe Temescal::Middleware do
111
113
  expect(code).to eq 404
112
114
  end
113
115
  end
116
+
117
+ context "with ignore_errors set" do
118
+ let(:middleware) do
119
+ Temescal::Middleware.new(app) do |config|
120
+ config.ignored_errors = StandardError, TypeError
121
+ config.monitors = :new_relic
122
+ end
123
+ end
124
+
125
+ it "should not log an ignored error type" do
126
+ expect($stderr).to_not receive(:print).with(an_instance_of String)
127
+
128
+ middleware.call env_for("http://foobar.com")
129
+ end
130
+
131
+ it "should not report an ignored error type" do
132
+ expect(Temescal::Monitors::NewRelic).to_not receive(:report).with(an_instance_of StandardError)
133
+
134
+ middleware.call env_for("http://foobar.com")
135
+ end
136
+ end
114
137
  end
115
138
 
116
139
  context "Override middleware to raise exception" do
data/spec/spec_helper.rb CHANGED
@@ -1,20 +1,23 @@
1
- if ENV['CI']
2
- require 'coveralls'
1
+ if ENV["CI"]
2
+ require "coveralls"
3
3
  Coveralls.wear!
4
4
  else
5
- require 'awesome_print'
6
- require 'pry-debugger'
5
+ require "awesome_print"
6
+ require "pry-debugger"
7
7
 
8
- require 'simplecov'
8
+ require "simplecov"
9
9
  SimpleCov.start
10
10
  end
11
11
 
12
- require 'rack'
12
+ require "rack"
13
13
 
14
- require 'airbrake'
15
- require 'newrelic_rpm'
14
+ require "airbrake"
15
+ require "newrelic_rpm"
16
16
 
17
- require 'temescal'
17
+ require "active_record"
18
+ require "sinatra"
19
+
20
+ require "temescal"
18
21
 
19
22
  RSpec.configure do |config|
20
23
  config.treat_symbols_as_metadata_keys_with_true_values = true
@@ -25,5 +28,5 @@ RSpec.configure do |config|
25
28
  # order dependency and want to debug it, you can fix the order by providing
26
29
  # the seed, which is printed after each run.
27
30
  # --seed 1234
28
- config.order = 'random'
31
+ config.order = "random"
29
32
  end
metadata CHANGED
@@ -1,41 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: temescal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Todd Bealmear
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-27 00:00:00.000000000 Z
11
+ date: 2014-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  description: Rack Middleware for gracefully handling exceptions for JSON APIs.
@@ -48,17 +48,19 @@ files:
48
48
  - LICENSE
49
49
  - README.md
50
50
  - Rakefile
51
- - lib/temescal.rb
51
+ - temescal.gemspec
52
52
  - lib/temescal/configuration.rb
53
+ - lib/temescal/error.rb
53
54
  - lib/temescal/middleware.rb
54
55
  - lib/temescal/monitors.rb
55
56
  - lib/temescal/response.rb
56
57
  - lib/temescal/version.rb
58
+ - lib/temescal.rb
57
59
  - spec/lib/temescal/configuration_spec.rb
60
+ - spec/lib/temescal/error_spec.rb
58
61
  - spec/lib/temescal/middleware_spec.rb
59
62
  - spec/lib/temescal/monitors_spec.rb
60
63
  - spec/spec_helper.rb
61
- - temescal.gemspec
62
64
  homepage: https://github.com/todd/temescal
63
65
  licenses:
64
66
  - MIT
@@ -69,17 +71,17 @@ require_paths:
69
71
  - lib
70
72
  required_ruby_version: !ruby/object:Gem::Requirement
71
73
  requirements:
72
- - - ">="
74
+ - - '>='
73
75
  - !ruby/object:Gem::Version
74
76
  version: '0'
75
77
  required_rubygems_version: !ruby/object:Gem::Requirement
76
78
  requirements:
77
- - - ">="
79
+ - - '>='
78
80
  - !ruby/object:Gem::Version
79
81
  version: '0'
80
82
  requirements: []
81
83
  rubyforge_project:
82
- rubygems_version: 2.2.0
84
+ rubygems_version: 2.0.3
83
85
  signing_key:
84
86
  specification_version: 4
85
87
  summary: Rack Middleware for gracefully handling exceptions for JSON APIs.