Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4b27794
Add one_email_per_occurrence option and migration task
imageaid Jul 17, 2024
b11b32f
standard.rb fixes
imageaid Jul 17, 2024
d466265
Adjustments from feedback on PR
imageaid Jul 18, 2024
bba0eb1
Refactor solid_errors_tasks.rake to remove hardcoded migrations
imageaid Jul 18, 2024
8d9505d
Rework 'prev_resolved_at' from error_params
imageaid Jul 18, 2024
429d2ac
Refactor email sending condition in SolidErrors
imageaid Jul 18, 2024
1391b73
Remove one_email_per_occurrence config option from SolidErrors
imageaid Jul 18, 2024
6ce78ba
Better README update for explaining new behavior
imageaid Jul 18, 2024
03d6cec
Make email sending condition consistent style; update migration copyi…
imageaid Jul 18, 2024
4882100
Update file existence check in solid_errors_tasks
imageaid Jul 18, 2024
9d22f4b
Simplify file search in solid_errors_tasks rake task
imageaid Jul 19, 2024
d9e7ee8
Update README.md
imageaid Jul 19, 2024
2f76f69
Update lib/tasks/solid_errors_tasks.rake
imageaid Jul 19, 2024
2214f49
Update lib/tasks/solid_errors_tasks.rake
imageaid Jul 19, 2024
5bc0fdd
Update README and solid_errors tasks
imageaid Jul 19, 2024
b912495
Forgot to remove an underscore
imageaid Jul 19, 2024
461fe22
bumping version so I can test migration copying
imageaid Jul 22, 2024
8c5415b
a little more tweaking to test migration copy
imageaid Jul 22, 2024
ae54100
another test run
imageaid Jul 22, 2024
0b80dd8
version bump 0.4.3.003
imageaid Jul 23, 2024
1bba415
Add full backtrace option and refine error handling.
imageaid Dec 2, 2024
59db8e1
Bumping version
imageaid Dec 2, 2024
28f610a
Upgrade solid_errors gem and fix backtrace logic.
imageaid Dec 2, 2024
fdf8906
Update backtrace regex, Ruby versions, and gem dependencies
imageaid Mar 27, 2025
df6b44f
Merge remote-tracking branch 'upstream/main'
imageaid Jun 10, 2025
5d0faf3
Update Gemfile.lock to remove actionmailer dependency
imageaid Jun 10, 2025
cf0afbc
Merge remote-tracking branch 'upstream/main'
imageaid Jun 17, 2025
40e4603
Fix incorrect variable usage in backtrace handling
imageaid Jun 22, 2025
4d80f4e
Bump version to 0.7.1, refine email handling and optimize resolved er…
imageaid Jul 10, 2025
6c28ace
Update `should_send_email?` logic and bump `solid_errors` to 0.7.2
imageaid Jul 10, 2025
b4be15a
Update `should_send_email?` logic and bump `solid_errors` to 0.7.3
imageaid Jul 10, 2025
870b713
Update `should_send_email?` logic and bump `solid_errors` to 0.7.4
imageaid Jul 10, 2025
2f634fc
Update `send_email` logic and bump `solid_errors` to 0.7.5
imageaid Jul 10, 2025
7f8005c
Bump `solid_errors` to 0.7.5 in Gemfile.lock
imageaid Jul 10, 2025
83d4b6c
Update `send_email` and `should_send_email?` logic, add `prev_resolve…
imageaid Aug 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
.DS_Store
test/dummy/log/*.log
test/dummy/db/*.sqlite3
.idea
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
solid_errors (0.7.0)
solid_errors (0.7.5)
actionpack (>= 7.0)
actionview (>= 7.0)
activerecord (>= 7.0)
Expand Down
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ authenticate :user, -> (user) { user.admin? } do
end
```

After updating the gem, run the migration installer so that any new migrations are copied over:
```bash
$ rails solid_errors:install_migrations
```

> [!NOTE]
> Be sure to [secure the dashboard](#authentication) in production.

Expand Down Expand Up @@ -247,10 +252,13 @@ Second, you can set the values via the configuration object:
config.solid_errors.send_emails = true
config.solid_errors.email_from = "errors@myapp.com"
config.solid_errors.email_to = "devs@myapp.com"
# Tell Solid Errors whether or not to limit the total emails per occurrence. Defaults to false.
config.solid_errors.email_subject_prefix = "[#{Rails.application.name}][#{Rails.env}]"
```

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.
If you have set `send_emails` to `true` and have set an `email_to` address, Solid Errors will send an email notification when an error first occurs. Subsequent occurrences of the error will not trigger additional emails to be sent; however, if an error is resolved and then reoccurs, an email will be sent, again, on the first reoccurrence of the error.

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.

#### Automatically destroying old records

Expand Down
15 changes: 14 additions & 1 deletion app/models/solid_errors/occurrence.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module SolidErrors
class Occurrence < Record
belongs_to :error, class_name: "SolidErrors::Error"

after_create_commit :send_email, if: -> { SolidErrors.send_emails? && SolidErrors.email_to.present? }
after_create :send_email, if: :should_send_email?
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think we need to change the after_create_commit.

after_create_commit :clear_resolved_errors, if: :should_clear_resolved_errors?

# The parsed exception backtrace. Lines in this backtrace that are from installed gems
Expand Down Expand Up @@ -45,5 +45,18 @@ def should_clear_resolved_errors?

true
end

def should_send_email?
return false unless SolidErrors.send_emails? && SolidErrors.email_to.present?
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a regression, the default is currently we send email whenever an error occured.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely and that is exactly what I do not want in my app (an email for every time an error occurs). It would send 20 in instances where an error occurred multiple times (like in a job that gets re-run, etc.).

This is what I need it to do. So, I will close the PR and continue down my fork. Thanks for the review!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, this is not a rejection, I'm not even the maintainer :). I just want to see this feature get attention and ultimately merged into the main repo. In term of regression, this is ultimately not me who decide, this gem is pre 1.0 so i guess regression is fine ? Other option is we can have an option to enable this feature.


# Check if resolved_at changed from a datetime to nil (resolved error reoccurred)
resolved_at_changes = error.previous_changes['resolved_at']
resolved_error_reoccurred = resolved_at_changes&.first.present? && resolved_at_changes&.last.nil?

# Check if this is the first occurrence of a brand new error
first_occurrence = error.occurrences.count == 1

resolved_error_reoccurred || first_occurrence
end
end
end
1 change: 1 addition & 0 deletions lib/generators/solid_errors/install/install_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def configure_solid_errors
'\1config.solid_errors.send_emails = true',
'\1config.solid_errors.email_from = ""',
'\1config.solid_errors.email_to = ""',
'\1config.solid_errors.full_backtrace = false',
'\1config.solid_errors.username = Rails.application.credentials.dig(:solid_errors, :username)',
'\1config.solid_errors.password = Rails.application.credentials.dig(:solid_errors, :password)'
].join("\n")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
t.text "severity", null: false
t.text "source"
t.datetime "resolved_at"
t.datetime "prev_resolved_at"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dont see this being used? to my understanding, the way we are currently checking it is by checking wether resolved_at previously has value or not.

t.string "fingerprint", limit: 64, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["fingerprint"], name: "index_solid_errors_on_fingerprint", unique: true
t.index ["resolved_at"], name: "index_solid_errors_on_resolved_at"
t.index ["prev_resolved_at"], name: "index_solid_errors_on_prev_resolved_at"
end

create_table "solid_errors_occurrences", force: :cascade do |t|
Expand Down
8 changes: 8 additions & 0 deletions lib/solid_errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

module SolidErrors
mattr_accessor :connects_to
mattr_accessor :full_backtrace
mattr_accessor :base_controller_class, default: "::ActionController::Base"
mattr_writer :username
mattr_writer :password
Expand All @@ -18,6 +19,13 @@ module SolidErrors

class << self
# use method instead of attr_accessor to ensure
# this works if variable set after SolidErrors is loaded
def full_backtrace?
@full_backtrace ||= ENV["SOLIDERRORS_FULL_BACKTRACE"] || @@full_backtrace || false
end

# use method instead of attr_accessor to ensure
# this works if variable set after SolidErrors is loaded
# this works if ENV variable set after SolidErrors is loaded
def username
@username ||= ENV["SOLIDERRORS_USERNAME"] || @@username
Expand Down
44 changes: 24 additions & 20 deletions lib/solid_errors/subscriber.rb
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
module SolidErrors
class Subscriber
IGNORED_ERRORS = ["ActionController::RoutingError",
"AbstractController::ActionNotFound",
"ActionController::MethodNotAllowed",
"ActionController::UnknownHttpMethod",
"ActionController::NotImplemented",
"ActionController::UnknownFormat",
"ActionController::InvalidAuthenticityToken",
"ActionController::InvalidCrossOriginRequest",
"ActionDispatch::Http::Parameters::ParseError",
"ActionController::BadRequest",
"ActionController::ParameterMissing",
"ActiveRecord::RecordNotFound",
"ActionController::UnknownAction",
"ActionDispatch::Http::MimeNegotiation::InvalidType",
"Rack::QueryParser::ParameterTypeError",
"Rack::QueryParser::InvalidParameterError",
"CGI::Session::CookieStore::TamperedWithCookie",
"Mongoid::Errors::DocumentNotFound",
"Sinatra::NotFound",
"Sidekiq::JobRetry::Skip"].map(&:freeze).freeze
"AbstractController::ActionNotFound",
"ActionController::MethodNotAllowed",
"ActionController::UnknownHttpMethod",
"ActionController::NotImplemented",
"ActionController::UnknownFormat",
"ActionController::InvalidAuthenticityToken",
"ActionController::InvalidCrossOriginRequest",
"ActionDispatch::Http::Parameters::ParseError",
"ActionController::BadRequest",
"ActionController::ParameterMissing",
"ActiveRecord::RecordNotFound",
"ActionController::UnknownAction",
"ActionDispatch::Http::MimeNegotiation::InvalidType",
"Rack::QueryParser::ParameterTypeError",
"Rack::QueryParser::InvalidParameterError",
"CGI::Session::CookieStore::TamperedWithCookie",
"Mongoid::Errors::DocumentNotFound",
"Sinatra::NotFound",
"Sidekiq::JobRetry::Skip"].map(&:freeze).freeze

def report(error, handled:, severity:, context:, source: nil)
return if ignore_by_class?(error.class.name)
Expand All @@ -37,9 +37,13 @@ def report(error, handled:, severity:, context:, source: nil)
record = SolidErrors::Error.create!(error_attributes.merge(fingerprint: fingerprint))
end

backtrace_cleaner = ActiveSupport::BacktraceCleaner.new
backtrace_cleaner.add_silencer { |line| /puma|rubygems|gems/.match?(line) }
backtrace = SolidErrors.full_backtrace? ? error.backtrace : backtrace_cleaner.clean(error.backtrace)

SolidErrors::Occurrence.create(
error_id: record.id,
backtrace: error.backtrace&.join("\n"),
backtrace: backtrace&.join("\n"),
context: s(context)
)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/solid_errors/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module SolidErrors
VERSION = "0.7.0"
VERSION = "0.8.0"
end