beekeeper 0.1.7

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ec711a53303d9fb0e5f4ee680e81e058ffc46e1652a91ca4bee3dcb05f7b81cc
4
+ data.tar.gz: 4efc54f12c5499769992c5d3e05f644d0b9fe8ff09369d31f2e9f82d8d1bf98b
5
+ SHA512:
6
+ metadata.gz: ad035c428b70925a0d27bd6aa4ed1373133009c1f806df0a1b93021e4f541146460d2deeace4cbdde664ab904e46844352f61a5976545dc0b34a0827715f390f
7
+ data.tar.gz: b62a386d0d7acb6270e247cb7c885211d00ca1fdf34c3498b8674e584b8b14097dc9a9e6d843118d62eb54adc15807b0926259ea8d702e81d28f3018d66a4725
@@ -0,0 +1,20 @@
1
+ Copyright 2020
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,48 @@
1
+ # Beekeeper
2
+ This is a library for error processing, logging and rendering.
3
+
4
+ ## Description
5
+
6
+ * This gem prints an error and a trimmed down version of the backtrace in case of ANY non-200 response in any application.
7
+ * This gem enables the application code(models, controllers and libs) code to be clean and concise. Since, now, we are handling the exceptions in a middleware, there is no need for ANY `re-raising exception` code in our models, controllers and other files.
8
+ * Application code should just contain the happy path and raise `known errors` if required. Other than that, no exception related code is required in the application code.
9
+ * This gem renders a standard JSON error response in case there is any error when calling an API route (`/api`). Currently, if there is any error, an HTML response is returned even if a JSON API route is called.
10
+
11
+
12
+ ## Installation
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'beekeeper'
17
+ ```
18
+
19
+ And then execute:
20
+ ```bash
21
+ $ bundle
22
+ ```
23
+
24
+ Or install it yourself as:
25
+ ```bash
26
+ $ gem install beekeeper
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ * Include `Beekeeper::Rescuer` in your application controller so that known errors are logged and response is returned in a standard JSON format.
32
+ * These are the `known errors` it rescues:
33
+ * `CustomErrors`
34
+ * `BaseError`
35
+ * `ActiveRecord::RecordInvalid` (Validation errors)
36
+ * `ActiveRecord::RecordNotFound`
37
+
38
+ * This library also inserts a `TrapApiExceptions` middleware in your Rails application stack which traps errors from an API route (`/api`) and returns a standard JSON error response by default. (Without this middleware, an HTML response is returned)
39
+
40
+ ## Usage
41
+
42
+ * Define `CustomErrors` in this gem and let other Rails apps inherit or use this in their apps.
43
+
44
+ ## Contributing
45
+ Contribution directions go here.
46
+
47
+ ## License
48
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,27 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Beekeeper'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ require 'bundler/gem_tasks'
18
+
19
+ require 'rake/testtask'
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'test'
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = false
25
+ end
26
+
27
+ task default: :test
@@ -0,0 +1,5 @@
1
+ require "beekeeper/railtie"
2
+ require "beekeeper/rescuer"
3
+ require "beekeeper/trap_api_exceptions"
4
+ require "beekeeper/error"
5
+ require "beekeeper/logger"
@@ -0,0 +1,32 @@
1
+ module Beekeeper
2
+ class Error < StandardError
3
+
4
+ attr_reader :status_code, :errors, :data, :status
5
+
6
+ def initialize(status_code, msg, options = {})
7
+ super(msg)
8
+ @status_code = status_code
9
+ @errors = get_errors(options)
10
+ @data = options[:data] || {}
11
+ @status = @status_code
12
+ end
13
+
14
+ def get_errors(options)
15
+ return [options.delete(:error)] if options[:error].present?
16
+ return options[:errors].errors().messages() if options[:errors].class < ActiveRecord::Base
17
+ return options[:error_map] if options[:error_map]
18
+ return options[:errors] || [{
19
+ code: class_name(options),
20
+ message: self.message
21
+ }]
22
+ end
23
+
24
+ private
25
+
26
+ def class_name options
27
+ return options[:exception].class.to_s if options[:exception].present?
28
+ self.class.to_s
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,51 @@
1
+ require 'blueprinter'
2
+ module Beekeeper
3
+ class ExceptionBlueprinter < Blueprinter::Base
4
+
5
+ view :basic do
6
+ field :status do |exception, options|
7
+ exception.try(:status) || get_status(exception, options)
8
+ end
9
+ field :message
10
+ field :error do |exception, options|
11
+ exception.try(:error) || get_error(exception, options)
12
+ end
13
+ field :errors do |exception, options|
14
+ exception.try(:errors) || get_errors(exception)
15
+ end
16
+ field :data do |exception, options|
17
+ exception.try(:data) || {}
18
+ end
19
+ end
20
+
21
+ def self.get_status exception, options
22
+ exception.try(:status) || get_status_from_backtrace(exception, options)
23
+ end
24
+
25
+ def self.get_error exception, options
26
+ status = get_status exception, options
27
+ Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500])
28
+ end
29
+
30
+ def self.get_status_from_backtrace exception, options
31
+ request = options[:request]
32
+ backtrace_cleaner = request.env['action_dispatch.backtrace_cleaner']
33
+ wrapper = ::ActionDispatch::ExceptionWrapper.new(backtrace_cleaner, exception)
34
+ return wrapper.status_code
35
+ end
36
+
37
+ def self.get_errors exception
38
+ return [
39
+ {
40
+ code: exception.class.name,
41
+ message: exception.message
42
+ }
43
+ ]
44
+ end
45
+
46
+ private
47
+
48
+
49
+ end
50
+ end
51
+
@@ -0,0 +1,37 @@
1
+ module Beekeeper
2
+ class Logger
3
+ def self.fatal(error)
4
+ message = if error.respond_to? :backtrace
5
+ message_with_backtrace(error)
6
+ else
7
+ error
8
+ end
9
+ Rails.logger.fatal message
10
+ end
11
+
12
+ def self.error(error)
13
+ message = if error.respond_to? :backtrace
14
+ message_with_backtrace(error)
15
+ else
16
+ error
17
+ end
18
+ Rails.logger.error message
19
+ end
20
+
21
+ private
22
+
23
+ def self.message_with_backtrace(error)
24
+ trace = clean(error.backtrace)
25
+ "\n#{error.class.name} (#{error.message}):\n#{trace.join}"
26
+ end
27
+
28
+ def self.clean(backtrace)
29
+ bc = ActiveSupport::BacktraceCleaner.new
30
+ bc.add_filter { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
31
+ bc.add_silencer { |line| line =~ /puma|rubygems|vendor|bin/ } # skip any lines from puma or rubygems
32
+ bc.clean(backtrace).map! { |t| " #{t}\n" }
33
+ end
34
+
35
+ end
36
+ end
37
+
@@ -0,0 +1,4 @@
1
+ module Beekeeper
2
+ class Railtie < ::Rails::Railtie
3
+ end
4
+ end
@@ -0,0 +1,26 @@
1
+ require 'beekeeper/exception_blueprinter'
2
+ module Beekeeper
3
+ module Rescuer
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ RESCUABLE_ERRORS = [
8
+ ::Beekeeper::Error,
9
+ ::Apipie::Error,
10
+ ::ActiveRecord::RecordInvalid
11
+ ]
12
+
13
+ rescue_from(*RESCUABLE_ERRORS, with: :handle_error)
14
+
15
+ def handle_error(error)
16
+ Logger.error(error)
17
+ response = ExceptionBlueprinter.render_as_hash error, view: :basic, request: request
18
+ render json: response, status: response[:status]
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+ end
25
+
26
+
@@ -0,0 +1,60 @@
1
+ require 'beekeeper/exception_blueprinter'
2
+ class Beekeeper::Railtie
3
+ initializer 'beekeeper.trap_api_exceptions' do |app|
4
+ # Global exception handler. No need of any exception handling in the application code.
5
+ app.middleware.insert_after(ActionDispatch::ShowExceptions, Beekeeper::TrapApiExceptions)
6
+ end
7
+ end
8
+
9
+ module Beekeeper
10
+ class TrapApiExceptions
11
+ def initialize(app)
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ request = ActionDispatch::Request.new env
17
+ @app.call(env)
18
+ rescue StandardError => e
19
+ if request.path_info.include? '/api'
20
+ render_json_error(request, e)
21
+ else
22
+ raise e
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def render_json_error(request, exception)
29
+ response = ExceptionBlueprinter.render_as_hash(exception, view: :basic, request: request)
30
+ body = response.to_json
31
+ return [
32
+ response[:status],
33
+ {
34
+ 'Content-Type' => "json; charset=#{::ActionDispatch::Response.default_charset}",
35
+ 'Content-Length' => body.bytesize.to_s
36
+ },
37
+ [body]
38
+ ]
39
+ end
40
+
41
+ def get_status(request, exception)
42
+ backtrace_cleaner = request.get_header 'action_dispatch.backtrace_cleaner'
43
+ wrapper = ::ActionDispatch::ExceptionWrapper.new(backtrace_cleaner, exception)
44
+ return wrapper.status_code
45
+ end
46
+
47
+ def get_error(status)
48
+ Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500])
49
+ end
50
+
51
+ def get_errors(exception)
52
+ return [
53
+ {
54
+ code: exception.class.name,
55
+ message: exception.message
56
+ }
57
+ ]
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,3 @@
1
+ module Beekeeper
2
+ VERSION = '0.1.7'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :beekeeper do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: beekeeper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.7
5
+ platform: ruby
6
+ authors:
7
+ - Omkar Joshi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-08-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.1.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.1.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: blueprinter
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.23.4
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.23.4
41
+ - !ruby/object:Gem::Dependency
42
+ name: oj
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.10.6
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.10.6
55
+ description: 'Beekeepeer: This gem is responsible for error logging, processing and
56
+ rendering of errors in a standard JSON format..'
57
+ email:
58
+ - omkar.joshi@anarock.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - MIT-LICENSE
64
+ - README.md
65
+ - Rakefile
66
+ - lib/beekeeper.rb
67
+ - lib/beekeeper/error.rb
68
+ - lib/beekeeper/exception_blueprinter.rb
69
+ - lib/beekeeper/logger.rb
70
+ - lib/beekeeper/railtie.rb
71
+ - lib/beekeeper/rescuer.rb
72
+ - lib/beekeeper/trap_api_exceptions.rb
73
+ - lib/beekeeper/version.rb
74
+ - lib/tasks/beekeeper_tasks.rake
75
+ homepage: https://github.com/saas-bn/beekeeper
76
+ licenses:
77
+ - MIT
78
+ metadata:
79
+ allowed_push_host: https://rubygems.org
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubygems_version: 3.0.3
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: 'Beekeeper: Error logging, processing and rendering.'
99
+ test_files: []