error_ready 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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: 1e90f8389acb8f9a4e9779fe63efb2c309122728f81e22c50e39442473c7ea07
4
+ data.tar.gz: 625c141100d154184fec324588b2d18eefda838d87d2b1abb5645969cc1edf20
5
5
  SHA512:
6
- metadata.gz: 2fd231f46958d06ec1aef6421e52113b6172ae3470e9f93fd3e2134224be7a3c7ddadd102a30c95cd928ef85e4a96c81d7ea476fa3c31a3a35c12f2b1c739b8d
7
- data.tar.gz: bcaa37cfcbf86880a73fac9eb7de3b0795f867520eb56137b14bf2e9af1bc2606c8f8a638c4ccf5af2b0622c33e655ba9bf910f72339f2f336aa5bbcd7de98e8
6
+ metadata.gz: 4e1054614f11a5b695482511fe73dcc905673f2e9c405a2b081a2256711526db81b420d189a85611a93faa4067485e805e9c42a70f84318f227453579b874640
7
+ data.tar.gz: c993186bf5697f498401411d49f0f03f3aa355fa06fd0de8f7102339687aca2a22b9511d0e39d2e2f097cf19d2f3354bcb324b2cb48c904a22e7c37b83f8c4a4
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_json
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.2"
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.2
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