Skip to content
This repository has been archived by the owner on Jun 27, 2022. It is now read-only.

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mtdowling committed Feb 28, 2014
0 parents commit 386ae56
Show file tree
Hide file tree
Showing 8 changed files with 462 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
@@ -0,0 +1,6 @@
.idea
.DS_STORE
coverage
phpunit.xml
composer.lock
vendor/
19 changes: 19 additions & 0 deletions LICENSE
@@ -0,0 +1,19 @@
Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
109 changes: 109 additions & 0 deletions README.rst
@@ -0,0 +1,109 @@
=====================
Guzzle Log Subscriber
=====================

Logs HTTP requests and responses to a `PSR-3 logger <https://github.com/php-fig/log>`_.

Here's a simple example of how it's used:

.. code-block:: php
use GuzzleHttp\Client;
use GuzzleHttp\Subscriber\Log\LogSubscruber;
use GuzzleHttp\Subscriber\Log\SimpleLogger;
$client = new Client();
// The log subscriber requires a PSR-3 logger. Guzzle provides a very
// simple implementation that can be used to log using echo, a fopen()
resource, or a callable function.
$logger = new SimpleLogger();
$subscriber = new LogSubscriber($logger);
$client->getEmitter()->addSubscriber($subscriber);
If you just want to quickly debug an issue, you can use the static
``getDebug()`` method of the LogSubscriber.

.. code-block:: php
$subscriber = LogSubscriber::getDebug();
$client->addSubscruber($subscriber);
The LogSubscriber's constructor accepts a logger as the first argument and a
message format string or a message formatter as the second argument.

.. code-block:: php
// Log the full request and response.
$subscriber = new LogSubscriber($logger, "{request}\n\n{response}");
Message Formatter
-----------------

Included in this repository is a *message formatter*. The message formatter is
used to format log messages for both requests and responses using a log
template that uses variable substitution for string enclosed in braces
(``{}``).

The following variables are available in message formatter templates:

{request}
Full HTTP request message

{response}
Full HTTP response message

{ts}
Timestamp

{host}
Host of the request

{method}
Method of the request

{url}
URL of the request

{protocol}
Request protocol

{version}
Protocol version

{resource}
Resource of the request (path + query + fragment)

{hostname}
Hostname of the machine that sent the request

{code}
Status code of the response (if available)

{phrase}
Reason phrase of the response (if available)

{error}
Any error messages (if available)

{req_header_*}
Replace ``*`` with the lowercased name of a request header to add to the
message.

{res_header_*}
Replace ``*`` with the lowercased name of a response header to add to the
message

{req_headers}
Request headers as a string.

{res_headers}
Response headers as a string.

{req_body}
Request body as a string.

{res_body}
Response body as a string.
22 changes: 22 additions & 0 deletions composer.json
@@ -0,0 +1,22 @@
{
"name": "guzzle/log-subscriber",
"description": "Logs HTTP requests and responses as they are sent over the wire (Guzzle 4+)",
"homepage": "http://guzzlephp.org/",
"keywords": ["plugin", "log", "guzzle"],
"license": "MIT",
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"require": {
"php": ">=5.4.0",
"guzzle/guzzle": "dev-guzzle4",
"psr/log": "~1.0"
},
"autoload": {
"psr-4": { "GuzzleHttp\\Subscriber\\Log\\": "src/" }
}
}
24 changes: 24 additions & 0 deletions phpunit.xml.dist
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./vendor/autoload.php"
colors="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader">

<testsuites>
<testsuite>
<directory>tests</directory>
</testsuite>
</testsuites>

<filter>
<whitelist>
<directory suffix=".php">src</directory>
</whitelist>
</filter>

</phpunit>
96 changes: 96 additions & 0 deletions src/LogSubscriber.php
@@ -0,0 +1,96 @@
<?php

namespace GuzzleHttp\Subscriber\Log;

use GuzzleHttp\Event\SubscriberInterface;
use GuzzleHttp\Event\CompleteEvent;
use GuzzleHttp\Event\ErrorEvent;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;

/**
* Plugin class that will add request and response logging to an HTTP request.
*
* The log plugin uses a message formatter that allows custom messages via
* template variable substitution.
*
* @see MessageLogger for a list of available template variable substitutions
*/
class LogSubscriber implements SubscriberInterface
{
/** @var LoggerInterface */
private $logger;

/** @var MessageFormatter Formatter used to format log messages */
private $formatter;

/**
* @param LoggerInterface $logger Logger used to log messages
* @param string|MessageFormatter $formatter Formatter used to format log messages or the formatter template
*/
public function __construct(LoggerInterface $logger, $formatter = null)
{
$this->logger = $logger;
$this->formatter = $formatter instanceof MessageFormatter
? $formatter
: new MessageFormatter($formatter);
}

/**
* Get a log plugin that outputs full request, response, and any error
* messages.
*
* @param resource $stream Stream to write to when logging. Defaults to STDOUT
*
* @return self
*/
public static function getDebugPlugin($stream = null)
{
return new self(
new SimpleLogger($stream),
"# Request:\n{request}\n# Response:\n{response}\n{error}"
);
}

public static function getSubscribedEvents()
{
return [
'complete' => ['onRequestAfterSend', -9999],
'error' => ['onRequestError', 9999]
];
}

/**
* @param CompleteEvent $event
*/
public function onRequestAfterSend(CompleteEvent $event)
{
$this->logger->log(
substr($event->getResponse()->getStatusCode(), 0, 1) == '2'
? LogLevel::INFO
: LogLevel::WARNING,
$this->formatter->format($event->getRequest(), $event->getResponse()),
[
'request' => $event->getRequest(),
'response' => $event->getResponse()
]
);
}

/**
* @param ErrorEvent $event
*/
public function onRequestError(ErrorEvent $event)
{
$ex = $event->getException();
$this->logger->log(
LogLevel::CRITICAL,
$this->formatter->format($event->getRequest(), $event->getResponse(), $ex),
[
'request' => $event->getRequest(),
'response' => $event->getResponse(),
'exception' => $ex
]
);
}
}

0 comments on commit 386ae56

Please sign in to comment.