.gitignore 0000666 00000000035 13052362222 0006533 0 ustar 00 /bin/
/composer.phar
/vendor/ DataCollector/GuzzleDataCollector.php 0000666 00000006620 13052362222 0013723 0 ustar 00 logAdapter = $logAdapter;
$this->requestFormatter = $requestFormatter;
$this->responseFormatter = $responseFormatter;
$this->data['requests'] = array();
}
/**
* {@inheritdoc}
*/
public function collect(Request $request, Response $response, \Exception $exception = null)
{
foreach ($this->logAdapter->getLogs() as $log) {
$requestId = spl_object_hash($log['extras']['request']);
if (isset($this->data['requests'][$requestId])) {
continue;
}
/** @var RequestInterface $guzzleRequest */
$guzzleRequest = $log['extras']['request'];
/** @var ResponseInterface $guzzleResponse */
$guzzleResponse = $log['extras']['response'];
$datum['message'] = $log['message'];
$datum['time'] = $log['extras']['time'];
$datum['request'] = $this->requestFormatter->format($guzzleRequest);
$datum['response'] = $this->responseFormatter->format($guzzleRequest, $guzzleResponse);
$datum['is_error'] = $this->isError($guzzleResponse);
$datum['status_code'] = $guzzleResponse->getStatusCode();
$datum['method'] = $guzzleRequest->getMethod();
$this->data['requests'][$requestId] = $datum;
}
}
/**
* @param ResponseInterface $response
* @return bool Returns true if response code is 4xx or 5xx
*/
protected function isError(ResponseInterface $response)
{
return $response->getStatusCode() >= 400 && $response->getStatusCode() < 600;
}
/**
* @return array List of requests with 4xx or 5xx response codes
*/
public function getErrorRequests()
{
return array_filter(
$this->getRequests(),
function ($item) {
return $item['is_error'];
}
);
}
/**
* @return array List of all requests
*/
public function getRequests()
{
return $this->data['requests'];
}
/**
* @return int Total requests duration
*/
public function getTotalDuration()
{
return array_reduce(
$this->getRequests(),
function ($carry, array $request) {
return $carry + $request['time'];
},
0
);
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'guzzle';
}
}
DependencyInjection/Compiler/ClientCompilerPass.php 0000666 00000003057 13052362222 0016516 0 ustar 00 findDefinition('emoe_guzzle.handler_stack');
$profilerMiddleware = $container->findDefinition('emoe_guzzle.request_profiler_middleware');
$profilerMiddleware->addMethodCall('attachMiddleware', [$stack]);
$loggerMiddleware = $container->findDefinition('emoe_guzzle.request_logger_middleware');
$loggerMiddleware->addMethodCall('attachMiddleware', [$stack]);
foreach ($container->findTaggedServiceIds('guzzle.client') as $id => $attributes) {
$definition = $container->getDefinition($id);
$arguments = $definition->getArguments();
if (isset($arguments[0]['handler'])) {
$stack = $arguments[0]['handler'];
$profilerMiddleware->addMethodCall('attachMiddleware', [$stack]);
$loggerMiddleware->addMethodCall('attachMiddleware', [$stack]);
}
$arguments[0]['handler'] = $stack;
$arguments[0]['profiler_middleware'] = $profilerMiddleware;
$arguments[0]['logger_middleware'] = $loggerMiddleware;
$definition->setArguments($arguments);
}
}
}
DependencyInjection/Compiler/MonologCompilerPass.php 0000666 00000002612 13052362222 0016706 0 ustar 00 has('monolog.logger') || false === $container->getParameter('emoe_guzzle.log.enabled')) {
return;
}
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../../Resources/config'));
$loader->load('monolog.yml');
$monologMiddleware = $container->findDefinition('emoe_guzzle.request_monolog_middleware');
foreach ($container->findTaggedServiceIds('guzzle.client') as $id => $attributes) {
$definition = $container->getDefinition($id);
$arguments = $definition->getArguments();
if (!isset($arguments[0]['handler'])) {
continue;
}
$stack = $arguments[0]['handler'];
$monologMiddleware->addMethodCall('attachMiddleware', [$stack]);
$arguments[0]['monolog_middleware'] = $monologMiddleware;
$definition->setArguments($arguments);
}
}
}
DependencyInjection/Configuration.php 0000666 00000002025 13052362222 0014005 0 ustar 00 root('emoe_guzzle');
$rootNode
->children()
->arrayNode('log')
->canBeDisabled()
->addDefaultsIfNotSet()
->children()
->scalarNode('format')->defaultValue('CLF')->end()
->end()
->end()
->end()
;
return $treeBuilder;
}
}
DependencyInjection/EmoeGuzzleExtension.php 0000666 00000002331 13052362222 0015161 0 ustar 00 processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
$container->setParameter('emoe_guzzle.log.enabled', $config['log']['enabled']);
$logFormat = $config['log']['format'];
if (in_array($logFormat, ['CLF', 'DEBUG', 'SHORT'])) {
$logFormat = constant('GuzzleHttp\\MessageFormatter::'.$logFormat);
}
$container->setParameter('emoe_guzzle.log.format', $logFormat);
}
}
EmoeGuzzleBundle.php 0000666 00000001126 13052362222 0010476 0 ustar 00 addCompilerPass(new ClientCompilerPass());
$container->addCompilerPass(new MonologCompilerPass());
}
}
Log/AbstractLogAdapter.php 0000666 00000000453 13052362222 0011507 0 ustar 00 log;
}
}
Log/ArrayLogAdapter.php 0000666 00000001162 13052362222 0011020 0 ustar 00 logs[] = array('message' => $message, 'priority' => $priority, 'extras' => $extras);
}
/**
* Get logged entries
*
* @return array
*/
public function getLogs()
{
return $this->logs;
}
/**
* Clears logged entries
*/
public function clearLogs()
{
$this->logs = array();
}
}
Log/LogAdapterInterface.php 0000666 00000000766 13052362222 0011653 0 ustar 00 Logger::DEBUG,
LOG_INFO => Logger::INFO,
LOG_WARNING => Logger::WARNING,
LOG_ERR => Logger::ERROR,
LOG_CRIT => Logger::CRITICAL,
LOG_ALERT => Logger::ALERT
);
public function __construct(Logger $logObject)
{
$this->log = $logObject;
}
public function log($message, $priority = LOG_INFO, $extras = array())
{
$this->log->addRecord(self::$mapping[$priority], $message, $extras);
}
}
Middleware/MiddlewareInterface.php 0000666 00000000510 13052362222 0013225 0 ustar 00 logAdapter = $logAdapter;
$this->stopwatch = $stopwatch;
$this->formatter = $formatter instanceof MessageFormatter ? $formatter : new MessageFormatter($formatter);
}
/**
* @inheritdoc
*/
public function attachMiddleware(HandlerStack $stack)
{
$stack->push(Middleware::mapRequest(function (RequestInterface $request) {
$this->onRequestBeforeSend($request);
return $request;
}));
$stack->push(function (callable $handler) {
return function (
RequestInterface $request,
array $options
) use ($handler) {
$promise = $handler($request, $options);
return $promise->then(
function (ResponseInterface $response) use ($request) {
$this->onRequestComplete($request, $response);
return $response;
}
);
};
});
return $stack;
}
/**
* Starts the stopwatch.
*
* @param RequestInterface $request
*/
private function onRequestBeforeSend(RequestInterface $request)
{
$hash = $this->hash($request);
$this->stopwatch->start($hash, self::NAME);
}
/**
* Stops the stopwatch.
*
* @param RequestInterface $request
* @param ResponseInterface $response
*/
private function onRequestComplete(RequestInterface $request, ResponseInterface $response)
{
$hash = $this->hash($request);
// Send the log message to the adapter, adding a category and host
$priority = $response && $this->isError($response) ? LOG_ERR : LOG_DEBUG;
$message = $this->formatter->format($request, $response);
$event = $this->stopwatch->stop($hash);
$this->logAdapter->log($message, $priority, array(
'request' => $request,
'response' => $response,
'time' => $event->getDuration(),
));
}
/**
* @param RequestInterface $request
*
* @return string
*/
private function hash(RequestInterface $request)
{
return spl_object_hash($request);
}
/**
* Checks if HTTP Status code is a Client Error (4xx)
*
* @param ResponseInterface $response
*
* @return bool
*/
public function isClientError(ResponseInterface $response)
{
return $response->getStatusCode() >= 400 && $response->getStatusCode() < 500;
}
/**
* Checks if HTTP Status code is Server OR Client Error (4xx or 5xx)
*
* @param ResponseInterface $response
*
* @return boolean
*/
public function isError(ResponseInterface $response)
{
return $this->isClientError($response) || $this->isServerError($response);
}
/**
* Checks if HTTP Status code is Server Error (5xx)
*
* @param ResponseInterface $response
*
* @return bool
*/
public function isServerError(ResponseInterface $response)
{
return $response->getStatusCode() >= 500 && $response->getStatusCode() < 600;
}
}
Middleware/RequestProfilerMiddleware.php 0000666 00000006137 13052362222 0014473 0 ustar 00 stopwatch = $stopwatch;
}
/**
* @inheritdoc
*/
public function attachMiddleware(HandlerStack $stack)
{
$stack->push(Middleware::mapRequest(function (RequestInterface $request) {
$this->onRequestBeforeSend($request);
return $request;
}));
$stack->push(function (callable $handler) {
return function (
RequestInterface $request,
array $options
) use ($handler) {
$promise = $handler($request, $options);
return $promise->then(
function (ResponseInterface $response) use ($request) {
$this->onRequestComplete($request);
return $response;
}
);
};
});
return $stack;
}
/**
* Starts the stopwatch.
*
* @param RequestInterface $request
*/
private function onRequestBeforeSend(RequestInterface $request)
{
if (null !== $this->stopwatch) {
$this->start($request);
}
}
/**
* Stops the stopwatch.
*
* @param RequestInterface $request
*/
private function onRequestComplete(RequestInterface $request)
{
if (null !== $this->stopwatch) {
$this->stop($request);
}
}
/**
* @param RequestInterface $request
*/
private function start(RequestInterface $request)
{
$this->requests[$this->hash($request)] = count($this->requests) + 1;
$name = $this->getEventName($request);
$this->stopwatch->start($name, self::NAME);
}
/**
* @param RequestInterface $request
*/
private function stop(RequestInterface $request)
{
$name = $this->getEventName($request);
$this->stopwatch->stop($name);
}
/**
* @param RequestInterface $request
*
* @return string
*/
private function hash(RequestInterface $request)
{
return spl_object_hash($request);
}
/**
* @param RequestInterface $request
*
* @return string
*/
private function getEventName(RequestInterface $request)
{
return sprintf(
'%s: [%d] %s %s',
self::NAME,
$this->requests[$this->hash($request)],
$request->getMethod(),
urldecode((string)$request->getUri())
);
}
}
README.md 0000666 00000007072 13052362222 0006032 0 ustar 00 # Symfony Guzzle6Bundle
[![Latest Stable Version](https://poser.pugx.org/e-moe/guzzle6-bundle/v/stable)](https://packagist.org/packages/e-moe/guzzle6-bundle)
[![Total Downloads](https://poser.pugx.org/e-moe/guzzle6-bundle/downloads)](https://packagist.org/packages/e-moe/guzzle6-bundle)
[![Latest Unstable Version](https://poser.pugx.org/e-moe/guzzle6-bundle/v/unstable)](https://packagist.org/packages/e-moe/guzzle6-bundle)
[![License](https://poser.pugx.org/e-moe/guzzle6-bundle/license)](https://packagist.org/packages/e-moe/guzzle6-bundle)
This bundle integrates [Guzzle 6.x][guzzle] into Symfony. Guzzle is a PHP framework for building RESTful web service clients.
## Requirements
- PHP 5.5 or above ([Guzzle 6][guzzle] requrenment)
- [Guzzle PHP Framework][guzzle] (included by composer)
- Symfony 2.7 or above (including Symfony 3.0)
## Installation
To install this bundle, run the command below and you will get the latest version by [Packagist][packagist].
``` bash
composer require e-moe/guzzle6-bundle
```
To use the newest (maybe unstable) version please add following into your composer.json:
``` json
{
"require": {
"e-moe/guzzle6-bundle": "dev-master"
}
}
```
## Usage
Load bundle in AppKernel.php:
``` php
new Emoe\GuzzleBundle\EmoeGuzzleBundle(),
```
Configuration in config.yml:
``` yaml
emoe_guzzle:
log:
enabled: true # Logging requests to Monolog
format: "Guzzle: [{ts}] \"{method} {uri} HTTP/{version}\" {code}" # Optional log format customization
```
Using services in controller:
``` php
$client = $this->get('guzzle.client');
$response = $client->get('http://example.com');
```
## Features
### Symfony Debug Profiler
### Symfony Debug Timeline
### Symfony Debug Toolbar
### Symfony Debug Logs (Monolog Integration)
## Suggestions
Adding aliases:
If you want to use different names for provided services you can use aliases. This is a good idea if you don't want
have any dependency to guzzle in your service name.
``` yaml
services:
http.client:
alias: guzzle.client
```
Creating multiple clients:
If you want to have different Guzzle clients in your application all you need is to define them in services file and
add "guzzle.client" tag to turn on Symfony integration (Debug toolbar, logs, so on..).
``` yaml
services:
guzzle.client_one:
class: %guzzle.client.class%
tags:
- { name: guzzle.client }
guzzle.client_two:
class: %guzzle.client.class%
tags:
- { name: guzzle.client }
```
## Authors
- Nikolay Labinskiy aka e-moe
Inspired by Chris Wilkinson's and Florian Preusner's GuzzleBundles ([1][misd-guzzle], [2][8p]).
See also the list of [contributors][contributors] who participated in this project.
## License
This bundle is released under the [MIT license](Resources/meta/LICENSE)
[guzzle]: http://guzzlephp.org/
[packagist]: https://packagist.org/packages/e-moe/guzzle6-bundle
[contributors]: https://github.com/e-moe/guzzle6-bundle/graphs/contributors
[misd-guzzle]: https://github.com/misd-service-development/guzzle-bundle
[8p]: https://github.com/8p/GuzzleBundle Resources/config/monolog.yml 0000666 00000001305 13052362222 0012160 0 ustar 00 parameters:
emoe_guzzle.monolog_log_adapter.class: Emoe\GuzzleBundle\Log\MonologLogAdapter
services:
emoe_guzzle.monolog_formatter:
class: %guzzle.formatter.class%
public: false
arguments:
- %emoe_guzzle.log.format%
emoe_guzzle.monolog_log_adapter:
class: %emoe_guzzle.monolog_log_adapter.class%
public: false
arguments:
- '@monolog.logger'
emoe_guzzle.request_monolog_middleware:
class: %emoe_guzzle.request_logger_middlware.class%
public: false
arguments:
- '@emoe_guzzle.monolog_log_adapter'
- '@emoe_guzzle.stopwatch'
- '@emoe_guzzle.monolog_formatter'
Resources/config/services.yml 0000666 00000004555 13052362222 0012343 0 ustar 00 parameters:
guzzle.client.class: GuzzleHttp\Client
guzzle.handler_stack.class: GuzzleHttp\HandlerStack
guzzle.formatter.class: GuzzleHttp\MessageFormatter
emoe_guzzle.request_profiler_middlware.class: Emoe\GuzzleBundle\Middleware\RequestProfilerMiddleware
emoe_guzzle.request_logger_middlware.class: Emoe\GuzzleBundle\Middleware\RequestLoggerMiddleware
emoe_guzzle.log_adapter.class: Emoe\GuzzleBundle\Log\ArrayLogAdapter
emoe_guzzle.data_collector.class: Emoe\GuzzleBundle\DataCollector\GuzzleDataCollector
emoe_guzzle.stopwatch.class: Symfony\Component\Stopwatch\Stopwatch
emoe_guzzle.request.format: "{request}"
emoe_guzzle.response.format: "{response}"
services:
emoe_guzzle.handler_stack:
class: %guzzle.handler_stack.class%
public: false
factory: [%guzzle.handler_stack.class%, create]
emoe_guzzle.request_profiler_middleware:
class: %emoe_guzzle.request_profiler_middlware.class%
public: false
arguments:
- '@debug.stopwatch'
emoe_guzzle.request_logger_middleware:
class: %emoe_guzzle.request_logger_middlware.class%
public: false
arguments:
- '@emoe_guzzle.log_adapter'
- '@emoe_guzzle.stopwatch'
- '@emoe_guzzle.message_formatter'
emoe_guzzle.stopwatch:
class: %emoe_guzzle.stopwatch.class%
public: false
emoe_guzzle.log_adapter:
class: %emoe_guzzle.log_adapter.class%
public: false
emoe_guzzle.message_formatter:
class: %guzzle.formatter.class%
public: false
emoe_guzzle.request_formatter:
class: %guzzle.formatter.class%
public: false
arguments:
- %emoe_guzzle.request.format%
emoe_guzzle.response_formatter:
class: %guzzle.formatter.class%
public: false
arguments:
- %emoe_guzzle.response.format%
emoe_guzzle.data_collector:
class: %emoe_guzzle.data_collector.class%
public: false
arguments:
- '@emoe_guzzle.log_adapter'
- '@emoe_guzzle.request_formatter'
- '@emoe_guzzle.response_formatter'
tags:
- { name: data_collector, template: "EmoeGuzzleBundle:Collector:guzzle", id: "guzzle" }
guzzle.client:
class: %guzzle.client.class%
tags:
- { name: guzzle.client }
Resources/doc/img/logs.png 0000666 00000341610 13052362222 0011517 0 ustar 00 PNG
IHDR R sRGB gAMA a pHYs od IDATx^sU%4?33w>3gQZi5VV*~F
hG 7Q(B 5J
7m9
5ؙ|ֵֺkd|{ڽ͵u~qq %A
( h @I@ J P 뮫[XhV 1&kooH V nSr8 rE϶o4 M< {i @QNe<1fKS0' r@_q&B4єi @~O6m
\V)ҥKM;cyd @Nɤ[n曯
Vɠ @L&ĝ