fix: preserve chained exception cause in logException#7
Open
alexstandiford wants to merge 1 commit into
Open
Conversation
logException previously logged only the outer exception's message and discarded the chain. Infrastructure exceptions (e.g. the PDO datastore backend) deliberately surface a stable, client-safe message and carry the real cause as a chained previous exception, so every datastore failure logged only "Failed to execute query." with the actual SQL error dropped. Walk the $e->getPrevious() chain and fold each non-empty message into the logged line. A level is skipped when its message is already embedded in a collected part (some wrappers embed the cause's text and also chain it), and the walk is bounded by a depth cap plus a cycle guard so the message can't grow without limit. Also drop the leading " - " separator that appeared when no prefix message was supplied.
5ec244f to
c49e928
Compare
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.
Problem
CanLogException::logException()logs only the outer exception's message and assigns the exception object tocontext['exception']— it never walksgetPrevious().This became a silent data-loss bug once infrastructure exceptions started carrying their real cause as a chained previous exception. The PDO datastore backend (
phpnomad/mysql-integration) deliberately throws:The generic outer message is intentional (SQL/driver detail must not reach clients), with the actual cause carried on the chain for loggers. But
logExceptiondiscarded the chain, so every datastore failure logged:…with the real error (column not found, duplicate key, constraint violation) gone. Downstream, consumers like Siren have ~360
logException($e)callsites that all went blind at once. The exception object incontext['exception']doesn't help listeners thatjson_encodecontext — anExceptionserializes to{}.Fix
Walk the
$e->getPrevious()chain and fold each non-empty message into the logged line. Consumer usage doesn't change — barelogException($e)now surfaces the real cause automatically.Folding the whole chain naively has two failure modes, both handled:
QueryStrategy:'Invalid query: ' . $e->getMessage()with$eas previous). A level is skipped when its message is already contained in a collected part, so it isn't logged twice.$maxLoggedExceptionDepth, default 10) plus a cycle guard, so a pathological chain can't produce a giant message.Also drops the spurious leading
" - "separator that appeared when no prefix message was supplied.Before:
After:
Tests
Adds
CanLogExceptionTest(11 tests): default/explicit level, context preservation, single- and multi-level chain flattening, the duplication-skip case, the depth cap, and the leading-separator fix. Full suite green; cs-fixer clean.Version bumped `1.2.1 → 1.2.2`.