error_ready 0.1.0 → 0.1.1

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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -3
  3. data/lib/error_ready/configuration.rb +9 -0
  4. data/lib/error_ready/formatter.rb +15 -6
  5. data/lib/error_ready/{rack_middleware.rb → middlewares/rack_middleware.rb} +5 -1
  6. data/lib/error_ready/notifiers/async_sender.rb +11 -0
  7. data/lib/error_ready/notifiers/sync_sender.rb +52 -0
  8. data/lib/error_ready/subscriber.rb +4 -4
  9. data/lib/error_ready/version.rb +1 -1
  10. data/lib/error_ready.rb +21 -3
  11. metadata +48 -23
  12. data/app/assets/config/error_ready_manifest.js +0 -1
  13. data/app/assets/images/error_ready/showcase.png +0 -0
  14. data/app/assets/stylesheets/error_ready/application.css +0 -15
  15. data/app/controllers/error_ready/application_controller.rb +0 -4
  16. data/app/controllers/error_ready/problems_controller.rb +0 -26
  17. data/app/helpers/error_ready/application_helper.rb +0 -4
  18. data/app/helpers/error_ready/problems_helper.rb +0 -4
  19. data/app/jobs/error_ready/application_job.rb +0 -4
  20. data/app/mailers/error_ready/application_mailer.rb +0 -6
  21. data/app/models/error_ready/application_record.rb +0 -5
  22. data/app/models/error_ready/notice.rb +0 -5
  23. data/app/models/error_ready/problem.rb +0 -15
  24. data/app/views/error_ready/problems/_problem.html.erb +0 -33
  25. data/app/views/error_ready/problems/index.html.erb +0 -10
  26. data/app/views/error_ready/problems/show.html.erb +0 -28
  27. data/app/views/layouts/error_ready/application.html.erb +0 -16
  28. data/config/routes.rb +0 -3
  29. data/db/migrate/20221005120809_create_error_ready_problems.rb +0 -16
  30. data/db/migrate/20221005135120_create_error_ready_notices.rb +0 -11
  31. data/lib/error_ready/notifiers/database.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54c1d662e9dc0e27d2c488f68e32a26bba5182884dcb6937bcf470bc61db8662
4
- data.tar.gz: 7a72b704734f9ae5644442df7d589571bff00488a705c0261d0daaf45964c2de
3
+ metadata.gz: cbb22eefa22cb717fc57d46ce807c6c587f42346ca975a12cea49745eb0c585a
4
+ data.tar.gz: b1cacd40f4c6df67a41b6678dd7498e23d3a584a97d10ab3882bfbb9feb67e8e
5
5
  SHA512:
6
- metadata.gz: 2fd231f46958d06ec1aef6421e52113b6172ae3470e9f93fd3e2134224be7a3c7ddadd102a30c95cd928ef85e4a96c81d7ea476fa3c31a3a35c12f2b1c739b8d
7
- data.tar.gz: bcaa37cfcbf86880a73fac9eb7de3b0795f867520eb56137b14bf2e9af1bc2606c8f8a638c4ccf5af2b0622c33e655ba9bf910f72339f2f336aa5bbcd7de98e8
6
+ metadata.gz: 3e4600c348fc31858bccc1703289933de91631f97bf9fd4feefb8fe73394a41180f2db512471a6a11f3064225cb8c8f433c455e1c6eb1783e0ce2651410a0e39
7
+ data.tar.gz: ac4b9ceb1fc00a377a7892ade04562041d2a8c123bc3dce551890d3d00d539aa9a0e6b9341736ed5291765ccfe88faeeff63f6f0ec83ef3d31d4fe44a29b924c
data/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # ErrorReady
2
- A plugin thats records errors and store them in the database you already have.
3
-
4
- ![Showcase image](app/assets/images/error_ready/showcase.png)
2
+ Error recording for Rails 7 applications
5
3
 
6
4
  ## Usage
7
5
  coming soon
@@ -0,0 +1,9 @@
1
+ module ErrorReady
2
+ class Configuration
3
+ include ActiveSupport::Configurable
4
+
5
+ config_accessor :host, default: "https://errorready.com/api/problems"
6
+ config_accessor :database_notifier, default: false
7
+ config_accessor :app_secret
8
+ end
9
+ end
@@ -1,23 +1,32 @@
1
1
  module ErrorReady
2
2
  class Formatter
3
3
  def initialize(error:, handled:, severity:, context:, source: nil)
4
- @error = error
5
4
  @handled = handled
6
5
  @severity = severity
7
6
  @context = context
8
7
  @source = source
8
+ @error = wrapped_exception(error)
9
9
  end
10
10
 
11
11
  def format
12
12
  {
13
- message: @error.message,
14
- err_class: @error.class.to_s,
15
- backtrace: @error.backtrace,
13
+ message: @error.exception.message,
14
+ err_class: @error.exception.class.to_s,
16
15
  severity: @severity.to_s,
17
- context: @context.transform_values(&:to_s),
18
16
  source: @source,
19
- environment: Rails.env
17
+ environment: Rails.env,
18
+ context: @context.transform_values(&:to_s),
19
+ source_to_show: @error.source_extracts[@error.source_to_show_id],
20
+ application_trace: @error.application_trace,
21
+ full_trace: @error.full_trace
20
22
  }
21
23
  end
24
+
25
+ def wrapped_exception(error)
26
+ ActionDispatch::ExceptionWrapper.new(
27
+ Rails::BacktraceCleaner.new,
28
+ error
29
+ )
30
+ end
22
31
  end
23
32
  end
@@ -5,10 +5,14 @@ module ErrorReady
5
5
  end
6
6
 
7
7
  def call(env)
8
+ # Load session
9
+ env["rack.session"]["init"] = true
10
+
8
11
  Rails.error.set_context(
9
12
  server_name: env["SERVER_NAME"],
10
13
  http_host: env["HTTP_HOST"],
11
- http_user_agent: env["HTTP_USER_AGENT"]
14
+ http_user_agent: env["HTTP_USER_AGENT"],
15
+ session: env["rack.session"].to_h
12
16
  )
13
17
 
14
18
  Rails.error.record do
@@ -0,0 +1,11 @@
1
+ module ErrorReady
2
+ class AsyncSender
3
+ def initialize(formatted_error)
4
+ @error = formatted_error
5
+ end
6
+
7
+ def call
8
+ SyncSender.new(@error).async.call
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,52 @@
1
+ require "net/http"
2
+
3
+ module ErrorReady
4
+ class SyncSender
5
+ include Concurrent::Async
6
+
7
+ def initialize(formatted_error)
8
+ @error = formatted_error
9
+ end
10
+
11
+ def call
12
+ handle_response(send_request)
13
+ end
14
+
15
+ def send_request
16
+ http = Net::HTTP.new(uri.hostname, uri.port)
17
+ http.use_ssl = true if uri.port == 443
18
+ req = Net::HTTP::Post.new(uri)
19
+ req["Content-type"] = "application/json"
20
+ req["APP-SECRET"] = app_secret
21
+ req.body = @error.to_json
22
+ http.request(req)
23
+ end
24
+
25
+ def handle_response(response)
26
+ case response
27
+ when Net::HTTPSuccess, Net::HTTPOK
28
+ log_message("error sent to #{uri.hostname}", :green)
29
+ when Net::HTTPUnauthorized
30
+ log_message("unauthorized, ensure you add app_secret on config file")
31
+ when Net::HTTPBadRequest
32
+ log_message("bad request")
33
+ when HTTPServerError
34
+ log_message("server error")
35
+ else
36
+ log_message("something wrong")
37
+ end
38
+ end
39
+
40
+ def app_secret
41
+ ErrorReady.configuration.app_secret
42
+ end
43
+
44
+ def log_message(msg, color = :red)
45
+ Rails.logger.debug ActiveSupport::LogSubscriber.new.send(:color, "ErrorReady: #{msg}", color, true)
46
+ end
47
+
48
+ def uri
49
+ @uri ||= URI(ErrorReady.configuration.host)
50
+ end
51
+ end
52
+ end
@@ -2,15 +2,15 @@ module ErrorReady
2
2
  class Subscriber
3
3
  def report(error, handled:, severity:, context:, source: nil)
4
4
  formatted_error = Formatter.new(
5
- error: error,
5
+ error: error,
6
6
  handled: handled,
7
7
  severity: severity,
8
- context: context,
8
+ context: context,
9
9
  source: source
10
10
  ).format
11
11
 
12
- # Save to database
13
- Database.new(formatted_error).call
12
+ # send Async
13
+ AsyncSender.new(formatted_error).call
14
14
  end
15
15
  end
16
16
  end
@@ -1,3 +1,3 @@
1
1
  module ErrorReady
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/lib/error_ready.rb CHANGED
@@ -3,9 +3,27 @@ require "error_ready/engine"
3
3
 
4
4
  module ErrorReady
5
5
  autoload :Subscriber, "error_ready/subscriber"
6
- autoload :RackMiddleware, "error_ready/rack_middleware"
7
- autoload :Formatter, 'error_ready/formatter'
6
+ autoload :Formatter, "error_ready/formatter"
7
+ autoload :Configuration, "error_ready/configuration"
8
+
9
+ # middlewares
10
+ autoload :RackMiddleware, "error_ready/middlewares/rack_middleware"
8
11
 
9
12
  # notifiers
10
- autoload :Database, "error_ready/notifiers/database"
13
+ autoload :SyncSender, "error_ready/notifiers/sync_sender"
14
+ autoload :AsyncSender, "error_ready/notifiers/async_sender"
15
+
16
+ class << self
17
+ def configuration
18
+ @configuration ||= Configuration.new
19
+ end
20
+
21
+ def configure
22
+ yield configuration
23
+ end
24
+
25
+ def root
26
+ File.dirname __dir__
27
+ end
28
+ end
11
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: error_ready
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moses Gathuku
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-07 00:00:00.000000000 Z
11
+ date: 2022-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -24,6 +24,48 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 7.0.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: concurrent-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: webmock
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: debug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
27
69
  description: Description of ErrorReady.
28
70
  email:
29
71
  - mosesgathuku95@gmail.com
@@ -34,30 +76,13 @@ files:
34
76
  - MIT-LICENSE
35
77
  - README.md
36
78
  - Rakefile
37
- - app/assets/config/error_ready_manifest.js
38
- - app/assets/images/error_ready/showcase.png
39
- - app/assets/stylesheets/error_ready/application.css
40
- - app/controllers/error_ready/application_controller.rb
41
- - app/controllers/error_ready/problems_controller.rb
42
- - app/helpers/error_ready/application_helper.rb
43
- - app/helpers/error_ready/problems_helper.rb
44
- - app/jobs/error_ready/application_job.rb
45
- - app/mailers/error_ready/application_mailer.rb
46
- - app/models/error_ready/application_record.rb
47
- - app/models/error_ready/notice.rb
48
- - app/models/error_ready/problem.rb
49
- - app/views/error_ready/problems/_problem.html.erb
50
- - app/views/error_ready/problems/index.html.erb
51
- - app/views/error_ready/problems/show.html.erb
52
- - app/views/layouts/error_ready/application.html.erb
53
- - config/routes.rb
54
- - db/migrate/20221005120809_create_error_ready_problems.rb
55
- - db/migrate/20221005135120_create_error_ready_notices.rb
56
79
  - lib/error_ready.rb
80
+ - lib/error_ready/configuration.rb
57
81
  - lib/error_ready/engine.rb
58
82
  - lib/error_ready/formatter.rb
59
- - lib/error_ready/notifiers/database.rb
60
- - lib/error_ready/rack_middleware.rb
83
+ - lib/error_ready/middlewares/rack_middleware.rb
84
+ - lib/error_ready/notifiers/async_sender.rb
85
+ - lib/error_ready/notifiers/sync_sender.rb
61
86
  - lib/error_ready/subscriber.rb
62
87
  - lib/error_ready/version.rb
63
88
  - lib/tasks/error_ready_tasks.rake
@@ -1 +0,0 @@
1
- //= link_directory ../stylesheets/error_ready .css
@@ -1,15 +0,0 @@
1
- /*
2
- * This is a manifest file that'll be compiled into application.css, which will include all the files
3
- * listed below.
4
- *
5
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
- * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
- *
8
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
- * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
- * files in this directory. Styles in this file should be added after the last require_* statement.
11
- * It is generally better to create a new file per style scope.
12
- *
13
- *= require_tree .
14
- *= require_self
15
- */
@@ -1,4 +0,0 @@
1
- module ErrorReady
2
- class ApplicationController < ActionController::Base
3
- end
4
- end
@@ -1,26 +0,0 @@
1
- module ErrorReady
2
- class ProblemsController < ApplicationController
3
- before_action :set_problem, only: %i[ show destroy ]
4
-
5
- # GET /problems
6
- def index
7
- @problems = Problem.latest_first
8
- end
9
-
10
- # GET /problems/1
11
- def show
12
- end
13
-
14
- # DELETE /problems/1
15
- def destroy
16
- @problem.destroy
17
- redirect_to problems_url, notice: "Problem was successfully destroyed."
18
- end
19
-
20
- private
21
- # Use callbacks to share common setup or constraints between actions.
22
- def set_problem
23
- @problem = Problem.find(params[:id])
24
- end
25
- end
26
- end
@@ -1,4 +0,0 @@
1
- module ErrorReady
2
- module ApplicationHelper
3
- end
4
- end
@@ -1,4 +0,0 @@
1
- module ErrorReady
2
- module ProblemsHelper
3
- end
4
- end
@@ -1,4 +0,0 @@
1
- module ErrorReady
2
- class ApplicationJob < ActiveJob::Base
3
- end
4
- end
@@ -1,6 +0,0 @@
1
- module ErrorReady
2
- class ApplicationMailer < ActionMailer::Base
3
- default from: "from@example.com"
4
- layout "mailer"
5
- end
6
- end
@@ -1,5 +0,0 @@
1
- module ErrorReady
2
- class ApplicationRecord < ActiveRecord::Base
3
- self.abstract_class = true
4
- end
5
- end
@@ -1,5 +0,0 @@
1
- module ErrorReady
2
- class Notice < ApplicationRecord
3
- belongs_to :problem, foreign_key: "error_ready_problem_id"
4
- end
5
- end
@@ -1,15 +0,0 @@
1
- module ErrorReady
2
- class Problem < ApplicationRecord
3
-
4
- has_many :notices, foreign_key: "error_ready_problem_id"
5
-
6
- attribute :first_notice_at, :datetime, default: Time.current
7
- attribute :last_notice_at, :datetime, default: Time.current
8
- attribute :notices_count, :integer, default: 0
9
-
10
- scope :resolved, -> { where.not(resolved_at: nil) }
11
- scope :unresolved, -> { where(resolved_at: nil) }
12
- scope :latest_first, -> { order(last_notice_at: :desc)}
13
-
14
- end
15
- end
@@ -1,33 +0,0 @@
1
- <li>
2
- <%= link_to problem_path(problem), class:"block hover:bg-gray-50" do %>
3
- <div class="flex items-center py-4 ">
4
- <div class="min-w-0 flex-1 sm:flex sm:items-center sm:justify-between">
5
- <div class="truncate">
6
- <div class="flex text-sm">
7
- <p class="truncate font-medium text-indigo-600"><%= problem.err_class %></p>
8
- <p class="ml-1 flex-shrink-0 font-normal text-gray-500">in <%= problem.environment %></p>
9
- </div>
10
- <div class="mt-2">
11
- <div class="flex items-center text-sm text-gray-500">
12
- <!-- Heroicon name: mini/calendar -->
13
- <svg class="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
14
- <path fill-rule="evenodd" d="M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z" clip-rule="evenodd" />
15
- </svg>
16
- <p>
17
- Last notice on
18
- <time datetime="2020-01-07"><%= problem.last_notice_at %></time>
19
- </p>
20
- </div>
21
- <div class="mt-2">
22
- <span class="text-gray-700 text-sm truncate"><%= problem.message %></span>
23
- </div>
24
- </div>
25
- </div>
26
-
27
- </div>
28
- <div class="ml-5 flex-shrink-0 text-green-600">
29
- <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
30
- </div>
31
- </div>
32
- <% end %>
33
- </li>
@@ -1,10 +0,0 @@
1
- <p style="color: green"><%= notice %></p>
2
- <div class="mt-3">
3
- <h1 class="font-bold text-gray-700 leading-tight text-2xl">Problems</h1>
4
-
5
- <div id="problems" class="mt-3">
6
- <ul class="divide-y">
7
- <%= render @problems %>
8
- </ul>
9
- </div>
10
- </div>
@@ -1,28 +0,0 @@
1
-
2
- <div class="mt-6">
3
- <div class="flex justify-between items-center">
4
- <span class="font-bold text-gray-700 text-xl"><%= @problem.err_class %></span>
5
- <span class="bg-gray-200 rounded-md p-2 text-gray-800">Resolve</span>
6
- </div>
7
-
8
- <div>
9
- <span class="block font-semibold">message:</span>
10
- <%= @problem.message %>
11
- </div>
12
-
13
- <div class="mt-3">
14
- <span class="font-semibold">Context:</span>
15
- <% @problem.notices.first.context.each do |k,v| %>
16
- <span class="block"><%= k.gsub('_', ' ').capitalize %>: <%= v %></span>
17
- <% end %>
18
- </div>
19
-
20
- <div class="mt-3">
21
- <span class="font-semibold">Backtrace:</span>
22
- <div class="text-sm bg-gray-200 p-2">
23
- <% @problem.notices.first.backtrace.each do |trace| %>
24
- <span class="block"><%= trace %></span>
25
- <% end %>
26
- </div>
27
- </div>
28
- </div>
@@ -1,16 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>Error ready | <%= Rails.application.class.module_parent_name %></title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
7
-
8
- <%= stylesheet_link_tag "error_ready/application", media: "all" %>
9
- <script src="https://cdn.tailwindcss.com"></script>
10
- </head>
11
- <body class="min-h-screen">
12
- <div class="mx-auto md:max-w-4xl">
13
- <%= yield %>
14
- </div>
15
- </body>
16
- </html>
data/config/routes.rb DELETED
@@ -1,3 +0,0 @@
1
- ErrorReady::Engine.routes.draw do
2
- resources :problems
3
- end
@@ -1,16 +0,0 @@
1
- class CreateErrorReadyProblems < ActiveRecord::Migration[7.0]
2
- def change
3
- create_table :error_ready_problems do |t|
4
- t.text :message
5
- t.string :err_class
6
- t.string :environment
7
- t.string :severity
8
- t.datetime :first_notice_at
9
- t.datetime :last_notice_at
10
- t.integer :notices_count
11
- t.datetime :resolved_at
12
-
13
- t.timestamps
14
- end
15
- end
16
- end
@@ -1,11 +0,0 @@
1
- class CreateErrorReadyNotices < ActiveRecord::Migration[7.0]
2
- def change
3
- create_table :error_ready_notices do |t|
4
- t.references :error_ready_problem, null: false, foreign_key: true
5
- t.json :backtrace
6
- t.json :context
7
-
8
- t.timestamps
9
- end
10
- end
11
- end
@@ -1,33 +0,0 @@
1
- module ErrorReady
2
- class Database
3
- def initialize(formatted_error)
4
- @error = formatted_error
5
- end
6
-
7
- def call
8
- problem = ErrorReady::Problem.find_or_create_by(
9
- message: @error[:message],
10
- err_class: @error[:err_class],
11
- environment: @error[:environment],
12
- severity: @error[:severity]
13
- )
14
-
15
- create_notice(problem)
16
- end
17
-
18
- def create_notice(problem)
19
- ActiveRecord::Base.transaction do
20
- ErrorReady::Notice.create(
21
- problem: problem,
22
- backtrace: @error[:backtrace],
23
- context: @error[:context]
24
- )
25
-
26
- problem.update(
27
- notices_count: problem.notices_count + 1,
28
- last_notice_at: Time.current,
29
- )
30
- end
31
- end
32
- end
33
- end