Log exception rows at Rails' debug_exception_log_level instead of always fatal - #67
Merged
Merged
Conversation
When a controller raises, no response row is logged, so 5xx and rescued responses like RecordNotFound (404) are never recorded. The error row is always fatal, although the gem silences DebugExceptions, which honours config.action_dispatch.log_rescued_responses (Rails 7.0+) and config.action_dispatch.debug_exception_log_level (Rails 7.1+). The tests render exceptions like a production app and pin a response row with the status the client gets (500, 404 from rescue_responses, also when a template error wraps the exception), a fatal error row by default, no error row for rescued responses when log_rescued_responses is false, and the error row at debug_exception_log_level. The two existing specs that raise now expect the response row too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Points logtail-rack at the claude/response-on-exception branch of logtail-ruby-rack in the root Gemfile and in every gemfiles/*.gemfile, so CI exercises HTTPEvents.status_for_exception. To be replaced by a follow-up commit that requires logtail-rack ~> 0.2, >= 0.2.9 once it's released. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…og settings The integration sets HTTPEvents.status_for_exception to ActionDispatch::ExceptionWrapper.new(nil, exception).status_code, the status ShowExceptions renders: config.action_dispatch.rescue_responses (404 for ActiveRecord::RecordNotFound), with ActionView::Template::Error unwrapped the way each Rails version does it, 500 otherwise. ErrorEvent now reads the request env keys DebugExceptions reads, whose logging the gem silences: no error row for rescued responses when action_dispatch.log_rescued_responses is false (Rails 7.0+), and the row at action_dispatch.debug_exception_log_level (Rails 7.1+). Without them, every exception is logged at fatal as before. The settings specs now change Rails.application.env_config, as Rails merges it into every request env and overrides per-request values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
logtail-rack 0.2.8 times responses with the monotonic clock, which Timecop doesn't freeze, so "Completed 200 OK in 0.0ms" no longer holds. The last CI run on main still resolved logtail-rack 0.2.7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ErrorEvent logged inside its rescue without a guard, so an error while building or writing the error event replaced the exception of the app. A StandardError there now goes to Logtail::Config.instance.debug, and the original exception is always re-raised. Kept local to ErrorEvent, so this doesn't depend on logtail-rack's log_safely. Both tests failed before the guard: the IOError of the logger and the ArgumentError of the event builder propagated instead of the app's error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… says config.load_defaults 7.1 sets config.action_dispatch.debug_exception_log_level to :error, so following it would turn every exception row of most modern apps, real 500s included, from fatal into error and break alerts on level = fatal. That is too big a change for a patch release, so the error row keeps its fatal level, as on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ErrorEvent stops reading action_dispatch.debug_exception_log_level and logs at fatal exactly as on main, since load_defaults 7.1 sets it to :error for most apps. Following it may come in a minor release. Honouring log_rescued_responses, the status resolver and the logging guard stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ErrorEvent has logged every exception at fatal since the gem's first version. Rails 7.1 added config.action_dispatch.debug_exception_log_level, the level DebugExceptions logs exceptions at (railtie default :fatal, config.load_defaults 7.1 and later set :error), but the gem silences DebugExceptions' logging, so the setting never reached the exception rows. The test that pinned the row at fatal under :error now expects error, and new tests pin: :warn logs the RuntimeError and the rescued RecordNotFound at warn, an app that doesn't set it keeps Rails' :fatal, and on Rails before 7.1, which has no such setting, every exception stays fatal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ErrorEvent reads the request env key action_dispatch.debug_exception_log_level the way DebugExceptions does (Rails copies the configured level into every request env as a Logger severity) and logs the exception row at that level. Without the key, on Rails before 7.1, the row stays fatal. This brings back the code that 6d8e4c9 took out of the 0.2.15 patch. Apps on config.load_defaults 7.1 or later now get their exception rows at error instead of fatal, so alerts and saved searches on level = fatal need adjusting. Setting debug_exception_log_level to :fatal keeps the old level. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PetrHeinz
marked this pull request as ready for review
October 2, 2026 09:23
…eleased" This reverts commit 15f9f96.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…' into claude/exception-log-level
PetrHeinz
changed the base branch from
claude/exception-response-status
to
main
October 2, 2026 12:04
…level main has #64 as one squashed commit, so lib/logtail-rails/error_event.rb and spec/logtail-rails/error_event_spec.rb conflicted with this branch's copy of #64. Both are resolved to this branch's side, which is main's #64 plus this PR's change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The gem's
ErrorEventmiddleware has logged every exception at level fatal since the gem's initial commit (v0.1.0, 2021-02-13). Rails 7.1 (October 2023) addedconfig.action_dispatch.debug_exception_log_level, the levelActionDispatch::DebugExceptionslogs exceptions at. Its railtie default is:fatal, butconfig.load_defaults "7.1"and later set it to:error. The gem silencesDebugExceptions' own logging (its logger is nil) and logs the exception row itself, so apps never got the level they configured in Rails. This is a long-standing gap, not a regression.What changes:
ErrorEventreads the request env keyaction_dispatch.debug_exception_log_level, the same wayDebugExceptionsdoes (request.get_header(...)→logger.add(level, ...)). Rails copies the configured level into every request env as aLoggerseverity, and the exception row is logged at that level.log_rescued_responsescheck, the guard that keeps the app's exception the one that propagates, and the response rows with the real status (500, or 404 forRecordNotFound).Behaviour change, for the 0.3.0 release notes:
config.load_defaults "7.1"or later now get their exception rows at level error instead of fatal. Alerts or saved searches that filter onlevel = fatalneed adjusting to include error.config.action_dispatch.debug_exception_log_level = :fatal. The gem silences Rails' own exception logging, so this only changes the rows sent to Better Stack.:warnis followed too. Like Rails' own logging, a level below the logger's level isn't sent at all, so:debugwithconfig.log_level = :infosends no exception rows. The response rows are still sent.:fatal, and Rails before 7.1 stays at fatal.