Skip to content

[Messenger] Allow fine-grained control in log severity of failures #44120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

jorissteyn
Copy link

This PR adds a new interface method on the RetryStrategyInterface allowing custom retry strategies to control the log severity of failed and retried messages.

This is a spin-off from #43160

Q A
Branch? 6.0
Bug fix? no
BC break? yes - custom retry strategies require including the new trait or implementing the new method
New feature? yes - changelog not yet updated
Deprecations? no
Tickets -
License MIT
Doc PR not yet, collecting feedback first

The default logic for determining the log severity for failed messages has been (since #43492):

  • recoverable exceptions are logged as warning
  • unrecoverable exceptions are logged as critical
  • neutral exceptions are logged as warning after a non-final attempt
  • neutral exceptions are logged as critical after a final attempt

This PR implements the exact same behaviour but in a way that allows users to augment or override the default behaviour with their own specific needs. For example, having specific exceptions logged as EMERGENCY or to log them as NOTICE until or including the last attempt.

The refactoring done to make this possible is:

  • move the logic determining if an exception is recoverable/unrecoverable/neutral to the HandlerFailedException so it can be used by retry strategy objects

  • add a new interface method on the RetryStrategyInterface (BC break!)

  • implement the existing behaviour using the new mechanism in a trait, this way, custom retry strategies can easily re-use the
    default behaviour

@carsonbot carsonbot added this to the 6.0 milestone Nov 17, 2021
@jorissteyn jorissteyn force-pushed the feature/retry-strategy-log-severity branch from 0e287ec to 2704917 Compare November 17, 2021 23:49
@jorissteyn jorissteyn force-pushed the feature/retry-strategy-log-severity branch 2 times, most recently from 143756b to 573b8b9 Compare November 18, 2021 00:23
@jorissteyn jorissteyn changed the title Allow fine-grained control in log severity of failures [Messenger] Allow fine-grained control in log severity of failures Nov 18, 2021
This commit adds a new interface method on the `RetryStrategyInterface`
allowing custom retry strategies to control the log severity of failed
and retried messages.

This is a spin-off from symfony#43160

| Q             | A
| ------------- | ---
| Branch?       | 6.0
| Bug fix?      | no
| BC break? | yes - custom retry strategies require including the new trait or implementing the new method
| New feature?  | yes - changelog not yet updated
| Deprecations? | no
| Tickets       | -
| License       | MIT
| Doc PR        | not yet, collecting feedback first

The default logic for determining the log severity for failed messages
has been (since symfony#43492):

 - recoverable exceptions are logged as warning
 - unrecoverable exceptions are logged as critical
 - neutral exceptions are logged as warning after a non-final attempt
 - neutral exceptions are logged as critical after a final attempt

This PR implements the exact same behaviour but in a way that allows
users to augment or override the default behaviour with their own
specific needs. For example, having specific exceptions logged as
`EMERGENCY` or to log them as `NOTICE` until or including the last
attempt.

The refactoring done to make this possible is:

 - move the logic determining if an exception is
   recoverable/unrecoverable/neutral to the `HandlerFailedException`
   so it can be used by retry strategy objects

 - add a new interface method on the `RetryStrategyInterface` (BC
   break!)

 - implement the existing behaviour using the new mechanism in a
   trait, this way, custom retry strategies can easily re-use the
   default behaviour
@jorissteyn jorissteyn force-pushed the feature/retry-strategy-log-severity branch from 573b8b9 to afb90f7 Compare November 18, 2021 00:30
@carsonbot
Copy link

Hey!

I think @nikophil has recently worked with this code. Maybe they can help review this?

Cheers!

Carsonbot

*
* If ALL nested Exceptions are an instance of UnrecoverableExceptionInterface the failure is unrecoverable
*/
public function isUnrecoverable(): bool
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure this business logic should belong to this HandlerFailedException class.

I suggest using the existing getNestedExceptionOfClass instead.

return false;
}

if ($this->isRecoverable($throwable)) {
Copy link
Member

Choose a reason for hiding this comment

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

the isRecoverable should be checked first.
In previous implementation if the exception contains both recoverable and unrecoverable the method shouldRetry returned true

Comment on lines -62 to +60
$shouldRetry = $retryStrategy && $this->shouldRetry($throwable, $envelope, $retryStrategy);
$shouldRetry = $retryStrategy && $retryStrategy->isRetryable($envelope, $throwable);
Copy link
Member

Choose a reason for hiding this comment

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

this should be reverted.
You moved the logic about Recoverability from SendFailedMessageForRetryListener to the MultiplierRetryStrategy but here, the retry retryStrategy is an RetryStrategyInterface. If people inject another instance, the behavior will not be preserved.

/**
* @return string The \Psr\Log\LogLevel log severity
*/
public function getLogSeverity(Envelope $message, \Throwable $throwable = null): string;
Copy link
Member

Choose a reason for hiding this comment

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

that's a BC break you must provide migration path in lower versions

And, I've not convinced this method should be part of this interface

@fabpot fabpot modified the milestones: 6.0, 6.1 Nov 21, 2021
@fabpot
Copy link
Member

fabpot commented Mar 26, 2022

@jorissteyn Are you still interested in moving this PR forward?

@fabpot fabpot modified the milestones: 6.1, 6.2 May 20, 2022
@fabpot
Copy link
Member

fabpot commented Jul 29, 2022

Closing as stalled.

@fabpot fabpot closed this Jul 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants