solid_errors 0.6.1 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acc9e46b7ee94e391df6d5fa4b11fd0550dcef9eca0f1b2089ec8ea81d6dc47e
4
- data.tar.gz: 37fda129cbac297cb10da823a70188515f29f57f02160b2acf01fd010345698a
3
+ metadata.gz: 877768652877df99eb678441601fa65e3329ad898ae4a163c2a260e5ab88d40b
4
+ data.tar.gz: dc5cd7fcb81f7548ea8657f74670971682f530c6149114b97bad9d943c282764
5
5
  SHA512:
6
- metadata.gz: 1f2cd0c74b2a38ac93abb353cc8083cb623b942cd117df06efaf246afc0e42e2cd40732692fb6e7510c2962fab5a3826d88c674c21d1c2582de8264a4ccbca82
7
- data.tar.gz: 1ecc1ebc03b277fa8840cdc3550ad0e64f566761a3ecdc5ad45a2daa39fde4b8922c528eec6fa3097fd15f098bfcbe7b372bc26197855e5507990d04e1729ce3
6
+ metadata.gz: 4482cfe25a500becec052384f224214e9946d97f1f034a03ea4d52f2549814863e00632da29b659bb78f9b0b58667a4773020141597f2e517be7dd08fbccb76c
7
+ data.tar.gz: bf4e567dcc81fe59ab1aac561abfd3110c69b83db080c317401caa19206f5e36c0e6b12a6afd6e232aeb883cfd85de822fa7fc802672348b01b3ca6aaa2ae32e
data/README.md CHANGED
@@ -98,6 +98,12 @@ end
98
98
 
99
99
  All exceptions are recorded automatically. No additional code required.
100
100
 
101
+ You can add default additional information to the context of the error by adding this line to your application controller:
102
+ ```ruby
103
+ before_action { Rails.error.set_context(request_url: request.original_url, params: params, session: session.inspect) }
104
+ ```
105
+ The additional context information will be automatically displayed on the occurence details page.
106
+
101
107
  Please consult the [official guides](https://guides.rubyonrails.org/error_reporting.html) for an introduction to the error reporting API.
102
108
 
103
109
  There are intentionally few features; you can view and resolve errors. That’s it. The goal is to provide a simple, lightweight, and performant solution for tracking exceptions in your Rails application. If you need more features, you should probably use a 3rd party service like [Honeybadger](https://www.honeybadger.io/), whose MIT-licensed [Ruby agent gem](https://github.com/honeybadger-io/honeybadger-ruby) provided a couple of critical pieces of code for this project.
@@ -160,10 +166,13 @@ You can configure Solid Errors via the Rails configuration object, under the `so
160
166
  * `sends_email` - Whether or not to send emails when an error occurs. See [Email notifications](#email-notifications) for more information.
161
167
  * `email_from` - The email address to send a notification from. See [Email notifications](#email-notifications) for more information.
162
168
  * `email_to` - The email address(es) to send a notification to. See [Email notifications](#email-notifications) for more information.
169
+ * `email_subject_prefix` - Prefix added to the subject line for email notifications. See [Email notifications](#email-notifications) for more information.
170
+ * `base_controller_class` - Specify a different controller as the base class for the Solid Errors controller. See [Authentication](#authentication) for more information.
171
+ * `destroy_after` - If set, Solid Errors will periodically destroy resolved records that are older than the value specified. See [Automatically destroying old records](#automatically-destroying-old-records) for more information.
163
172
 
164
- #### Database Configuration
173
+ ### Database Configuration
165
174
 
166
- `config.solid_errors.connects_to` takes a custom database configuration hash that will be used in the abstract `SolidErrors::Record` Active Record model. This is required to use a different database than the main app. For example:
175
+ `config.solid_errors.connects_to` takes a custom database configuration hash that will be used in the abstract `SolidErrors::Record` Active Record model. This is required to use a different database than the main app ([but the primary database can also be used](#single-database-configuration)). For example:
167
176
 
168
177
  ```ruby
169
178
  # Use a single separate DB for Solid Errors
@@ -177,6 +186,16 @@ or
177
186
  config.solid_errors.connects_to = { database: { writing: :solid_errors_primary, reading: :solid_errors_replica } }
178
187
  ```
179
188
 
189
+ #### Single Database Configuration
190
+
191
+ Running Solid Errors in a separate database is recommended, but it's also possible to use one single database for both the app and the errors. Just follow these steps to add errors to the primary database:
192
+
193
+ 1. Copy the contents of `db/errors_schema.rb` into a normal migration and delete `db/errors_schema.rb`
194
+ 2. Remove `config.solid_errors.connects_to` from your configuration files.
195
+ 3. Migrate your database.
196
+
197
+ You won't have multiple databases, so `database.yml` doesn't need to have the errors database configuration.
198
+
180
199
  #### Authentication
181
200
 
182
201
  Solid Errors does not restrict access out of the box. You must secure the dashboard yourself. However, it does provide basic HTTP authentication that can be used with basic authentication or Devise. All you need to do is setup a username and password.
@@ -206,9 +225,16 @@ authenticate :user, -> (user) { user.admin? } do
206
225
  end
207
226
  ```
208
227
 
228
+ You can also specify a different controller to use as the Solid Errors controller base class:
229
+
230
+ ```ruby
231
+ # Override the base controller class with your own controller
232
+ config.solid_errors.base_controller_class = "YourAdminController"
233
+ ```
234
+
209
235
  #### Email notifications
210
236
 
211
- Solid Errors _can_ send email notifications whenever an error occurs, if your application has ActionMailer already properly setup to send emails. However, in order to activate this feature you must define the email address(es) to send the notifications to. Optionally, you can also define the email address to send the notifications from (useful if your email provider only allows emails to be sent from a predefined list of addresses) or simply turn off this feature altogether.
237
+ Solid Errors _can_ send email notifications whenever an error occurs, if your application has ActionMailer already properly setup to send emails. However, in order to activate this feature you must define the email address(es) to send the notifications to. Optionally, you can also define the email address to send the notifications from (useful if your email provider only allows emails to be sent from a predefined list of addresses) or simply turn off this feature altogether. You can also define a subject prefix for the email notifications to quickly identify the source of the error.
212
238
 
213
239
  There are two ways to configure email notifications. First, you can use environment variables:
214
240
 
@@ -216,19 +242,35 @@ There are two ways to configure email notifications. First, you can use environm
216
242
  ENV["SOLIDERRORS_SEND_EMAILS"] = true # defaults to false
217
243
  ENV["SOLIDERRORS_EMAIL_FROM"] = "errors@myapp.com" # defaults to "solid_errors@noreply.com"
218
244
  ENV["SOLIDERRORS_EMAIL_TO"] = "devs@myapp.com" # no default, must be set
245
+ ENV["SOLIDERRORS_EMAIL_SUBJECT_PREFIX"] = "[Application name][Environment]" # no default, optional
219
246
  ```
220
247
 
221
248
  Second, you can set the values via the configuration object:
222
249
 
223
250
  ```ruby
224
- # Set authentication credentials for Solid Errors
251
+ # Set authentication credentials and optional subject prefix for Solid Errors
225
252
  config.solid_errors.send_emails = true
226
253
  config.solid_errors.email_from = "errors@myapp.com"
227
254
  config.solid_errors.email_to = "devs@myapp.com"
255
+ config.solid_errors.email_subject_prefix = "[#{Rails.application.name}][#{Rails.env}]"
228
256
  ```
229
257
 
230
258
  If you have set `send_emails` to `true` and have set an `email_to` address, Solid Errors will send an email notification whenever an error occurs. If you have not set `send_emails` to `true` or have not set an `email_to` address, Solid Errors will not send any email notifications.
231
259
 
260
+ #### Automatically destroying old records
261
+
262
+ Setting `destroy_after` to a duration will allow Solid Errors to be self-maintaining by peridically destroying **resolved** records that are older than that value. The value provided must respond to `.ago`.
263
+
264
+ ```ruby
265
+ # Automatically destroy records older than 30 days
266
+ config.solid_errors.destroy_after = 30.days
267
+ ```
268
+
269
+ ```ruby
270
+ # Automatically destroy records older than 6 months
271
+ config.solid_errors.destroy_after = 6.months
272
+ ```
273
+
232
274
  ### Examples
233
275
 
234
276
  There are only two screens in the dashboard.
@@ -311,9 +353,20 @@ You can always take control of the views by creating your own views and/or parti
311
353
  </html>
312
354
  ```
313
355
 
356
+ ## Sponsors
357
+
358
+ <p align="center">
359
+ <em>Proudly sponsored by</em>
360
+ </p>
361
+ <p align="center">
362
+ <a href="https://www.honeybadger.io?utm_source=fractaledmind&utm_medium=open-source&utm_campaign=solid_errors">
363
+ <img src="https://honeybadger-static.s3.amazonaws.com/brand_assets/honeybadger_logo/honeybadger_logo.svg" width="575" />
364
+ </a>
365
+ </p>
366
+
314
367
  ## Development
315
368
 
316
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
369
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. If you want to set up a local development database, run `rake db:migrate`.
317
370
 
318
371
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
319
372
 
@@ -328,3 +381,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
328
381
  ## Code of Conduct
329
382
 
330
383
  Everyone interacting in the SolidErrors project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/fractaledmind/solid_errors/blob/main/CODE_OF_CONDUCT.md).
384
+
data/Rakefile CHANGED
@@ -1,14 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bundler/setup"
4
+
5
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
6
+ load "rails/tasks/engine.rake"
7
+
3
8
  require "bundler/gem_tasks"
4
9
  require "rake/testtask"
10
+ require "standard/rake"
11
+
12
+ task default: %i[test standard]
5
13
 
6
14
  Rake::TestTask.new(:test) do |t|
7
15
  t.libs << "test"
8
16
  t.libs << "lib"
9
- t.test_files = FileList["test/**/test_*.rb"]
17
+ t.test_files = FileList["test/**/*_test.rb"]
10
18
  end
11
-
12
- require "standard/rake"
13
-
14
- task default: %i[test standard]
@@ -1,5 +1,6 @@
1
1
  module SolidErrors
2
- class ApplicationController < ActionController::Base
2
+ class ApplicationController < SolidErrors.base_controller_class.constantize
3
+ layout "solid_errors/application"
3
4
  protect_from_forgery with: :exception
4
5
 
5
6
  http_basic_authenticate_with name: SolidErrors.username, password: SolidErrors.password if SolidErrors.password
@@ -1,12 +1,18 @@
1
1
  module SolidErrors
2
2
  # adapted from: https://github.com/codergeek121/email_error_reporter/blob/main/lib/email_error_reporter/error_mailer.rb
3
- class ErrorMailer < ActionMailer::Base
3
+ class ErrorMailer < (defined?(ActionMailer::Base) ? ActionMailer::Base : Object)
4
4
  def error_occurred(occurrence)
5
+ unless defined?(ActionMailer::Base)
6
+ raise "ActionMailer is not available. Make sure that you require \"action_mailer/railtie\" in application.rb"
7
+ end
5
8
  @occurrence = occurrence
6
9
  @error = occurrence.error
7
-
10
+ subject = "#{@error.severity_emoji} #{@error.exception_class}"
11
+ if SolidErrors.email_subject_prefix.present?
12
+ subject = [SolidErrors.email_subject_prefix, subject].join(" ").squish!
13
+ end
8
14
  mail(
9
- subject: "#{@error.severity_emoji} #{@error.exception_class}",
15
+ subject: subject,
10
16
  from: SolidErrors.email_from,
11
17
  to: SolidErrors.email_to
12
18
  )
@@ -2,7 +2,7 @@ module SolidErrors
2
2
  # adapted from: https://github.com/honeybadger-io/honeybadger-ruby/blob/master/lib/honeybadger/backtrace.rb
3
3
  class BacktraceLine
4
4
  # Backtrace line regexp (optionally allowing leading X: for windows support).
5
- INPUT_FORMAT = %r{^((?:[a-zA-Z]:)?[^:]+):(\d+)(?::in `([^']+)')?$}
5
+ INPUT_FORMAT = %r{^((?:[a-zA-Z]:)?[^:]+):(\d+)(?::in [`']([^']+)')?$}
6
6
  STRING_EMPTY = "".freeze
7
7
  GEM_ROOT = "[GEM_ROOT]".freeze
8
8
  PROJECT_ROOT = "[PROJECT_ROOT]".freeze
@@ -3,6 +3,7 @@ module SolidErrors
3
3
  belongs_to :error, class_name: "SolidErrors::Error"
4
4
 
5
5
  after_create_commit :send_email, if: -> { SolidErrors.send_emails? && SolidErrors.email_to.present? }
6
+ after_create_commit :clear_resolved_errors, if: :should_clear_resolved_errors?
6
7
 
7
8
  # The parsed exception backtrace. Lines in this backtrace that are from installed gems
8
9
  # have the base path for gem installs replaced by "[GEM_ROOT]", while those in the project
@@ -23,5 +24,26 @@ module SolidErrors
23
24
  def send_email
24
25
  ErrorMailer.error_occurred(self).deliver_later
25
26
  end
27
+
28
+ def clear_resolved_errors
29
+ transaction do
30
+ SolidErrors::Occurrence
31
+ .where(error: SolidErrors::Error.resolved)
32
+ .where(created_at: ...SolidErrors.destroy_after.ago)
33
+ .delete_all
34
+ SolidErrors::Error.resolved
35
+ .where
36
+ .missing(:occurrences)
37
+ .delete_all
38
+ end
39
+ end
40
+
41
+ def should_clear_resolved_errors?
42
+ return false unless SolidErrors.destroy_after
43
+ return false unless SolidErrors.destroy_after.respond_to?(:ago)
44
+ return false unless (id % 100).zero?
45
+
46
+ true
47
+ end
26
48
  end
27
49
  end
@@ -10,6 +10,11 @@ module SolidErrors
10
10
  config.solid_errors.each do |name, value|
11
11
  SolidErrors.public_send(:"#{name}=", value)
12
12
  end
13
+
14
+ if SolidErrors.send_emails? && !defined?(ActionMailer)
15
+ raise "You have configured solid_errors.send_emails = true but ActionMailer is not available." \
16
+ "Make sure that you require \"action_mailer/railtie\" in application.rb or set solid_errors.send_emails = false."
17
+ end
13
18
  end
14
19
 
15
20
  initializer "solid_errors.active_record.error_subscriber" do
@@ -39,7 +39,7 @@ module SolidErrors
39
39
 
40
40
  SolidErrors::Occurrence.create(
41
41
  error_id: record.id,
42
- backtrace: error.backtrace.join("\n"),
42
+ backtrace: error.backtrace&.join("\n"),
43
43
  context: s(context)
44
44
  )
45
45
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidErrors
4
- VERSION = "0.6.1"
4
+ VERSION = "0.7.0"
5
5
  end
data/lib/solid_errors.rb CHANGED
@@ -7,35 +7,30 @@ require_relative "solid_errors/engine"
7
7
 
8
8
  module SolidErrors
9
9
  mattr_accessor :connects_to
10
+ mattr_accessor :base_controller_class, default: "::ActionController::Base"
10
11
  mattr_writer :username
11
12
  mattr_writer :password
12
- mattr_writer :send_emails
13
- mattr_writer :email_from
14
- mattr_writer :email_to
13
+ mattr_accessor :send_emails, default: false
14
+ mattr_accessor :email_from, default: "solid_errors@noreply.com"
15
+ mattr_accessor :email_to
16
+ mattr_accessor :email_subject_prefix
17
+ mattr_accessor :destroy_after
15
18
 
16
19
  class << self
17
20
  # use method instead of attr_accessor to ensure
18
- # this works if variable set after SolidErrors is loaded
21
+ # this works if ENV variable set after SolidErrors is loaded
19
22
  def username
20
23
  @username ||= ENV["SOLIDERRORS_USERNAME"] || @@username
21
24
  end
22
25
 
23
26
  # use method instead of attr_accessor to ensure
24
- # this works if variable set after SolidErrors is loaded
27
+ # this works if ENV variable set after SolidErrors is loaded
25
28
  def password
26
29
  @password ||= ENV["SOLIDERRORS_PASSWORD"] || @@password
27
30
  end
28
31
 
29
32
  def send_emails?
30
- @send_emails ||= ENV["SOLIDERRORS_SEND_EMAILS"] || @@send_emails || false
31
- end
32
-
33
- def email_from
34
- @email_from ||= ENV["SOLIDERRORS_EMAIL_FROM"] || @@email_from || "solid_errors@noreply.com"
35
- end
36
-
37
- def email_to
38
- @email_to ||= ENV["SOLIDERRORS_EMAIL_TO"] || @@email_to
33
+ send_emails && email_to.present?
39
34
  end
40
35
  end
41
36
  end
metadata CHANGED
@@ -1,29 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_errors
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Margheim
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-09-18 00:00:00.000000000 Z
10
+ date: 2025-06-11 00:00:00.000000000 Z
12
11
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: actionmailer
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '7.0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '7.0'
27
12
  - !ruby/object:Gem::Dependency
28
13
  name: actionpack
29
14
  requirement: !ruby/object:Gem::Requirement
@@ -108,7 +93,6 @@ dependencies:
108
93
  - - ">="
109
94
  - !ruby/object:Gem::Version
110
95
  version: '0'
111
- description:
112
96
  email:
113
97
  - stephen.margheim@gmail.com
114
98
  executables: []
@@ -154,7 +138,6 @@ licenses:
154
138
  metadata:
155
139
  homepage_uri: https://github.com/fractaledmind/solid_errors
156
140
  source_code_uri: https://github.com/fractaledmind/solid_errors
157
- post_install_message:
158
141
  rdoc_options: []
159
142
  require_paths:
160
143
  - lib
@@ -169,8 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
152
  - !ruby/object:Gem::Version
170
153
  version: '0'
171
154
  requirements: []
172
- rubygems_version: 3.5.11
173
- signing_key:
155
+ rubygems_version: 3.6.2
174
156
  specification_version: 4
175
157
  summary: Database-backed Rails error subscriber
176
158
  test_files: []