bug #32036 [Messenger] improve logs (Tobion)

This PR was merged into the 4.3 branch.

Discussion
----------

[Messenger] improve logs

| Q             | A
| ------------- | ---
| Branch?       | 4.3
| Bug fix?      | no
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| BC breaks?    | no     <!-- see https://symfony.com/bc -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass?   | yes    <!-- please add some, will be required by reviewers -->
| Fixed tickets |
| License       | MIT
| Doc PR        |

The logs are currently very confusing and duplicated:

- When handled sync the uncaught error it logged and displayed by the console / http error handler anyway. Currently it the warning is duplicated and useless:

```
14:26:11 WARNING   [messenger] An exception occurred while handling message "{class}": OUCH, THAT HURTS! GO TO MOM!
14:26:11 ERROR     [console] Error thrown while running command "{class}". Message: "OUCH, THAT HURTS! GO TO MOM!"

In HandleMessageMiddleware.php line 82:

  [Symfony\Component\Messenger\Exception\HandlerFailedException]
  OUCH, THAT HURTS! GO TO MOM!
```

- When handling async is was even confusing because the actual error was logged as warning and the retry (which is a good thing) was the error.

```
13:48:15 WARNING   [messenger] An exception occurred while handling message "{class}": OUCH, THAT HURTS! GO TO MOM!
13:48:15 ERROR     [messenger] Retrying {class} - retry #1.
```

Now it's must clearer and adds even context like the delay:

```
16:20:11 ERROR     [messenger] Error thrown while handling message {class}. Dispatching for retry #3 using 4000 ms delay. Error: "OUCH, THAT HURTS! GO TO MOM!"
...
16:20:15 CRITICAL  [messenger] Error thrown while handling message {class}. Removing from transport after 3 retries. Error: "OUCH, THAT HURTS! GO TO MOM!"
```

Commits
-------

2ac7027b71 [Messenger] improve logs
This commit is contained in:
Fabien Potencier 2019-06-14 07:10:33 +02:00
commit e02da2ab35
5 changed files with 38 additions and 50 deletions

View File

@ -64,7 +64,7 @@ class HandleMessageMiddleware implements MiddlewareInterface
$handler = $handlerDescriptor->getHandler();
$handledStamp = HandledStamp::fromDescriptor($handlerDescriptor, $handler($message));
$envelope = $envelope->with($handledStamp);
$this->logger->info('Message "{class}" handled by "{handler}"', $context + ['handler' => $handledStamp->getHandlerName()]);
$this->logger->info('Message {class} handled by {handler}', $context + ['handler' => $handledStamp->getHandlerName()]);
} catch (\Throwable $e) {
$exceptions[] = $e;
}
@ -75,7 +75,7 @@ class HandleMessageMiddleware implements MiddlewareInterface
throw new NoHandlerForMessageException(sprintf('No handler for message "%s".', $context['class']));
}
$this->logger->info('No handler for message "{class}"', $context);
$this->logger->info('No handler for message {class}', $context);
}
if (\count($exceptions)) {

View File

@ -54,37 +54,30 @@ class SendMessageMiddleware implements MiddlewareInterface
$sender = null;
try {
if ($envelope->all(ReceivedStamp::class)) {
// it's a received message, do not send it back
$this->logger->info('Received message "{class}"', $context);
} else {
/** @var RedeliveryStamp|null $redeliveryStamp */
$redeliveryStamp = $envelope->last(RedeliveryStamp::class);
if ($envelope->all(ReceivedStamp::class)) {
// it's a received message, do not send it back
$this->logger->info('Received message {class}', $context);
} else {
/** @var RedeliveryStamp|null $redeliveryStamp */
$redeliveryStamp = $envelope->last(RedeliveryStamp::class);
// dispatch event unless this is a redelivery
$shouldDispatchEvent = null === $redeliveryStamp;
foreach ($this->getSenders($envelope, $redeliveryStamp) as $alias => $sender) {
if (null !== $this->eventDispatcher && $shouldDispatchEvent) {
$event = new SendMessageToTransportsEvent($envelope);
$this->eventDispatcher->dispatch($event);
$envelope = $event->getEnvelope();
$shouldDispatchEvent = false;
}
$this->logger->info('Sending message "{class}" with "{sender}"', $context + ['sender' => \get_class($sender)]);
$envelope = $sender->send($envelope->with(new SentStamp(\get_class($sender), \is_string($alias) ? $alias : null)));
// dispatch event unless this is a redelivery
$shouldDispatchEvent = null === $redeliveryStamp;
foreach ($this->getSenders($envelope, $redeliveryStamp) as $alias => $sender) {
if (null !== $this->eventDispatcher && $shouldDispatchEvent) {
$event = new SendMessageToTransportsEvent($envelope);
$this->eventDispatcher->dispatch($event);
$envelope = $event->getEnvelope();
$shouldDispatchEvent = false;
}
}
if (null === $sender) {
return $stack->next()->handle($envelope, $stack);
$this->logger->info('Sending message {class} with {sender}', $context + ['sender' => \get_class($sender)]);
$envelope = $sender->send($envelope->with(new SentStamp(\get_class($sender), \is_string($alias) ? $alias : null)));
}
} catch (\Throwable $e) {
$context['exception'] = $e;
$this->logger->warning('An exception occurred while handling message "{class}": '.$e->getMessage(), $context);
}
throw $e;
if (null === $sender) {
return $stack->next()->handle($envelope, $stack);
}
// message should only be sent and not be handled by the next middleware

View File

@ -70,14 +70,14 @@ class MultiplierRetryStrategy implements RetryStrategyInterface
return true;
}
$retries = $this->getCurrentRetryCount($message);
$retries = RedeliveryStamp::getRetryCountFromEnvelope($message);
return $retries < $this->maxRetries;
}
public function getWaitingTime(Envelope $message): int
{
$retries = $this->getCurrentRetryCount($message);
$retries = RedeliveryStamp::getRetryCountFromEnvelope($message);
$delay = $this->delayMilliseconds * pow($this->multiplier, $retries);
@ -87,12 +87,4 @@ class MultiplierRetryStrategy implements RetryStrategyInterface
return $delay;
}
private function getCurrentRetryCount(Envelope $message): int
{
/** @var RedeliveryStamp|null $retryMessageStamp */
$retryMessageStamp = $message->last(RedeliveryStamp::class);
return $retryMessageStamp ? $retryMessageStamp->getRetryCount() : 0;
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Messenger\Stamp;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\Messenger\Envelope;
/**
* Stamp applied when a messages needs to be redelivered.
@ -38,6 +39,14 @@ class RedeliveryStamp implements StampInterface
$this->redeliveredAt = new \DateTimeImmutable();
}
public static function getRetryCountFromEnvelope(Envelope $envelope): int
{
/** @var self|null $retryMessageStamp */
$retryMessageStamp = $envelope->last(self::class);
return $retryMessageStamp ? $retryMessageStamp->getRetryCount() : 0;
}
public function getRetryCount(): int
{
return $this->retryCount;

View File

@ -140,14 +140,16 @@ class Worker implements WorkerInterface
$this->dispatchEvent(new WorkerMessageFailedEvent($envelope, $transportName, $throwable, $shouldRetry));
$retryCount = RedeliveryStamp::getRetryCountFromEnvelope($envelope);
if ($shouldRetry) {
$retryCount = $this->getRetryCount($envelope) + 1;
++$retryCount;
$delay = $retryStrategy->getWaitingTime($envelope);
if (null !== $this->logger) {
$this->logger->error('Retrying {class} - retry #{retryCount}.', $context + ['retryCount' => $retryCount, 'error' => $throwable]);
$this->logger->error('Error thrown while handling message {class}. Dispatching for retry #{retryCount} using {delay} ms delay. Error: "{error}"', $context + ['retryCount' => $retryCount, 'delay' => $delay, 'error' => $throwable->getMessage(), 'exception' => $throwable]);
}
// add the delay and retry stamp info + remove ReceivedStamp
$retryEnvelope = $envelope->with(new DelayStamp($retryStrategy->getWaitingTime($envelope)))
$retryEnvelope = $envelope->with(new DelayStamp($delay))
->with(new RedeliveryStamp($retryCount, $this->getSenderClassOrAlias($envelope)))
->withoutAll(ReceivedStamp::class);
@ -157,7 +159,7 @@ class Worker implements WorkerInterface
$receiver->ack($envelope);
} else {
if (null !== $this->logger) {
$this->logger->critical('Rejecting {class} (removing from transport).', $context + ['error' => $throwable]);
$this->logger->critical('Error thrown while handling message {class}. Removing from transport after {retryCount} retries. Error: "{error}"', $context + ['retryCount' => $retryCount, 'error' => $throwable->getMessage(), 'exception' => $throwable]);
}
$receiver->reject($envelope);
@ -207,14 +209,6 @@ class Worker implements WorkerInterface
return $retryStrategy->isRetryable($envelope);
}
private function getRetryCount(Envelope $envelope): int
{
/** @var RedeliveryStamp|null $retryMessageStamp */
$retryMessageStamp = $envelope->last(RedeliveryStamp::class);
return $retryMessageStamp ? $retryMessageStamp->getRetryCount() : 0;
}
private function getSenderClassOrAlias(Envelope $envelope): string
{
/** @var SentStamp|null $sentStamp */