[Messenger][SQS] Make sure one can enable debug logs

This commit is contained in:
Nyholm 2020-11-05 09:31:41 +01:00 committed by Robin Chalas
parent 57e39b41b9
commit 66edc59b56
7 changed files with 114 additions and 7 deletions

View File

@ -138,6 +138,7 @@
"twig/markdown-extra": "^2.12"
},
"conflict": {
"async-aws/core": "<1.5",
"doctrine/dbal": "<2.10",
"masterminds/html5": "<2.6",
"phpdocumentor/reflection-docblock": "<3.2.2",

View File

@ -128,6 +128,9 @@ return static function (ContainerConfigurator $container) {
->tag('kernel.reset', ['method' => 'reset'])
->set('messenger.transport.sqs.factory', AmazonSqsTransportFactory::class)
->args([
service('logger')->ignoreOnInvalid(),
])
->set('messenger.transport.beanstalkd.factory', BeanstalkdTransportFactory::class)

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
5.3.0
-----
* Added new `debug` option to log HTTP requests and responses.
5.2.0
-----

View File

@ -18,6 +18,9 @@ use AsyncAws\Sqs\Result\ReceiveMessageResult;
use AsyncAws\Sqs\SqsClient;
use AsyncAws\Sqs\ValueObject\Message;
use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\Connection;
use Symfony\Contracts\HttpClient\HttpClientInterface;
@ -179,7 +182,7 @@ class ConnectionTest extends TestCase
public function testFromDsnWithInvalidQueryString()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Unknown option found in DSN: [foo]. Allowed options are [buffer_size, wait_time, poll_timeout, visibility_timeout, auto_setup, access_key, secret_key, endpoint, region, queue_name, account, sslmode].');
$this->expectExceptionMessageMatches('|Unknown option found in DSN: \[foo\]\. Allowed options are \[buffer_size, |');
Connection::fromDsn('sqs://default?foo=foo');
}
@ -187,7 +190,7 @@ class ConnectionTest extends TestCase
public function testFromDsnWithInvalidOption()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Unknown option found: [bar]. Allowed options are [buffer_size, wait_time, poll_timeout, visibility_timeout, auto_setup, access_key, secret_key, endpoint, region, queue_name, account, sslmode].');
$this->expectExceptionMessageMatches('|Unknown option found: \[bar\]\. Allowed options are \[buffer_size, |');
Connection::fromDsn('sqs://default', ['bar' => 'bar']);
}
@ -195,7 +198,7 @@ class ConnectionTest extends TestCase
public function testFromDsnWithInvalidQueryStringAndOption()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Unknown option found: [bar]. Allowed options are [buffer_size, wait_time, poll_timeout, visibility_timeout, auto_setup, access_key, secret_key, endpoint, region, queue_name, account, sslmode].');
$this->expectExceptionMessageMatches('|Unknown option found: \[bar\]\. Allowed options are \[buffer_size, |');
Connection::fromDsn('sqs://default?foo=foo', ['bar' => 'bar']);
}
@ -312,4 +315,83 @@ class ConnectionTest extends TestCase
$connection->delete('id');
}
public function testLoggerWithoutDebugOption()
{
$client = new MockHttpClient([$this->getMockedQueueUrlResponse(), $this->getMockedReceiveMessageResponse()]);
$logger = $this->getMockBuilder(NullLogger::class)
->disableOriginalConstructor()
->onlyMethods(['debug'])
->getMock();
$logger->expects($this->never())->method('debug');
$connection = Connection::fromDsn('sqs://default', ['access_key' => 'foo', 'secret_key' => 'bar', 'auto_setup' => false], $client, $logger);
$connection->get();
}
public function testLoggerWithDebugOption()
{
$client = new MockHttpClient([$this->getMockedQueueUrlResponse(), $this->getMockedReceiveMessageResponse()]);
$logger = $this->getMockBuilder(NullLogger::class)
->disableOriginalConstructor()
->onlyMethods(['debug'])
->getMock();
$logger->expects($this->exactly(4))->method('debug');
$connection = Connection::fromDsn('sqs://default?debug=true', ['access_key' => 'foo', 'secret_key' => 'bar', 'auto_setup' => false], $client, $logger);
$connection->get();
}
private function getMockedQueueUrlResponse(): MockResponse
{
return new MockResponse(<<<XML
<GetQueueUrlResponse>
<GetQueueUrlResult>
<QueueUrl>https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue</QueueUrl>
</GetQueueUrlResult>
<ResponseMetadata>
<RequestId>470a6f13-2ed9-4181-ad8a-2fdea142988e</RequestId>
</ResponseMetadata>
</GetQueueUrlResponse>
XML
);
}
private function getMockedReceiveMessageResponse(): MockResponse
{
return new MockResponse(<<<XML
<ReceiveMessageResponse>
<ReceiveMessageResult>
<Message>
<MessageId>5fea7756-0ea4-451a-a703-a558b933e274</MessageId>
<ReceiptHandle>
MbZj6wDWli+JvwwJaBV+3dcjk2YW2vA3+STFFljTM8tJJg6HRG6PYSasuWXPJB+Cw
Lj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQ+QE
auMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=
</ReceiptHandle>
<MD5OfBody>fafb00f5732ab283681e124bf8747ed1</MD5OfBody>
<Body>This is a test message</Body>
<Attribute>
<Name>SenderId</Name>
<Value>195004372649</Value>
</Attribute>
<Attribute>
<Name>SentTimestamp</Name>
<Value>1238099229000</Value>
</Attribute>
<Attribute>
<Name>ApproximateReceiveCount</Name>
<Value>5</Value>
</Attribute>
<Attribute>
<Name>ApproximateFirstReceiveTimestamp</Name>
<Value>1250700979248</Value>
</Attribute>
</Message>
</ReceiveMessageResult>
<ResponseMetadata>
<RequestId>b6633655-283d-45b4-aee4-4e84e0ae6afa</RequestId>
</ResponseMetadata>
</ReceiveMessageResponse>
XML
);
}
}

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Messenger\Bridge\AmazonSqs\Transport;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
use Symfony\Component\Messenger\Transport\TransportFactoryInterface;
use Symfony\Component\Messenger\Transport\TransportInterface;
@ -20,11 +21,18 @@ use Symfony\Component\Messenger\Transport\TransportInterface;
*/
class AmazonSqsTransportFactory implements TransportFactoryInterface
{
private $logger;
public function __construct(LoggerInterface $logger = null)
{
$this->logger = $logger;
}
public function createTransport(string $dsn, array $options, SerializerInterface $serializer): TransportInterface
{
unset($options['transport_name']);
return new AmazonSqsTransport(Connection::fromDsn($dsn, $options), $serializer);
return new AmazonSqsTransport(Connection::fromDsn($dsn, $options, null, $this->logger), $serializer);
}
public function supports(string $dsn, array $options): bool

View File

@ -15,6 +15,7 @@ use AsyncAws\Sqs\Enum\QueueAttributeName;
use AsyncAws\Sqs\Result\ReceiveMessageResult;
use AsyncAws\Sqs\SqsClient;
use AsyncAws\Sqs\ValueObject\MessageAttributeValue;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Exception\InvalidArgumentException;
use Symfony\Component\Messenger\Exception\TransportException;
use Symfony\Contracts\HttpClient\HttpClientInterface;
@ -45,6 +46,7 @@ class Connection
'queue_name' => 'messages',
'account' => null,
'sslmode' => null,
'debug' => null,
];
private $configuration;
@ -85,8 +87,9 @@ class Connection
* * poll_timeout: amount of seconds the transport should wait for new message
* * visibility_timeout: amount of seconds the message won't be visible
* * auto_setup: Whether the queue should be created automatically during send / get (Default: true)
* * debug: Log all HTTP requests and responses as LoggerInterface::DEBUG (Default: false)
*/
public static function fromDsn(string $dsn, array $options = [], HttpClientInterface $client = null): self
public static function fromDsn(string $dsn, array $options = [], HttpClientInterface $client = null, LoggerInterface $logger = null): self
{
if (false === $parsedUrl = parse_url($dsn)) {
throw new InvalidArgumentException(sprintf('The given Amazon SQS DSN "%s" is invalid.', $dsn));
@ -124,6 +127,9 @@ class Connection
'accessKeyId' => urldecode($parsedUrl['user'] ?? '') ?: $options['access_key'] ?? self::DEFAULT_OPTIONS['access_key'],
'accessKeySecret' => urldecode($parsedUrl['pass'] ?? '') ?: $options['secret_key'] ?? self::DEFAULT_OPTIONS['secret_key'],
];
if (isset($options['debug'])) {
$clientConfiguration['debug'] = $options['debug'];
}
unset($query['region']);
if ('default' !== ($parsedUrl['host'] ?? 'default')) {
@ -152,7 +158,7 @@ class Connection
$queueUrl = 'https://'.$parsedUrl['host'].$parsedUrl['path'];
}
return new self($configuration, new SqsClient($clientConfiguration, null, $client), $queueUrl);
return new self($configuration, new SqsClient($clientConfiguration, null, $client, $logger), $queueUrl);
}
public function get(): ?array

View File

@ -17,9 +17,11 @@
],
"require": {
"php": ">=7.2.5",
"async-aws/core": "^1.5",
"async-aws/sqs": "^1.0",
"symfony/messenger": "^4.3|^5.0",
"symfony/service-contracts": "^1.1|^2"
"symfony/service-contracts": "^1.1|^2",
"psr/log": "^1.0"
},
"require-dev": {
"symfony/http-client-contracts": "^1.0|^2.0",