shrikeh / guzzle-middleware-response-timer

测量同步或异步连接的响应时间(毫秒)

0.3.3 2018-11-05 11:12 UTC

README

build_status_img sensiolabs_insight_img code_quality_img latest_stable_version_img versioneye_dependencies_img license_img twitter_img

这是一个简单的计时器和记录器,用于记录由Guzzle客户端对PSR-3日志发起请求的响应时间。最初创建是为了帮助Gousto了解微服务是如何交互和执行的。

与其他一些现有的计时器相比,它有一些优势,例如它原生支持异步调用,并且使用Request对象本身作为键,因此可以分别记录对同一URI的多次调用。

安装

建议使用composer进行安装

composer require shrikeh/guzzle-middleware-response-timer

要求和版本控制

如果通过composer安装,所有要求都应得到妥善处理。使用了语义版本控制,并且在标签1.0及以后版本中严格遵守;之前的分支相对更自由,因为我当时正在探索想法和接口。

标签<2.0与5.6兼容;2.0及更高版本仅支持PHP 7.1及以上。

基本用法

以下是一个使用quickStart()方法的简单示例,该方法接受一个Psr\Log\LoggerInterface记录器(在这种情况下,一个由Monolog实现的简单文件流)

<?php

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Promise;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Shrikeh\GuzzleMiddleware\TimerLogger\Middleware;

require_once __DIR__.'/../vendor/autoload.php';

$logFile = __DIR__.'/logs/example.log';
$logFile = new SplFileObject($logFile, 'w+');

// create a log channel
$log = new Logger('guzzle');
$log->pushHandler(new StreamHandler(
    $logFile->getRealPath(),
    Logger::DEBUG
));

// hand it to the middleware (this will create a default working example)
$middleware = Middleware::quickStart($log);

// now create a Guzzle middleware stack
$stack = HandlerStack::create();

// and register the middleware on the stack
$stack->push($middleware());

$config = [
    'timeout'   => 2,
    'handler' => $stack,
];

// then hand the stack to the client
$client = new Client($config);

$promises = [
    'facebook'  => $client->getAsync('https://#'),
    'wikipedia' => $client->getAsync('https://en.wikipedia.org/wiki/Main_Page'),
    'google'    => $client->getAsync('https://www.google.co.uk'),
];

$results = Promise\settle($promises)->wait();

print $logFile->fread($logFile->getSize());

异常处理

默认情况下,Middleware::quickStart()方法使用一个TriggerErrorHandler启动startstop处理器,该处理器简单地吞咽抛出的任何异常,并生成一个E_USER_NOTICE错误。这是为了确保任何与日志记录的问题都不会导致任何应用程序级别的问题:没有默认情况会导致记录响应时间的问题会破坏你的应用程序。同样,由于异常最可能是与底层的Logger有关,因此不会记录抛出的异常。

如果你希望抛出异常并不同地处理它们,请使用实现ExceptionHandlerInterface的实例加载处理器。

服务提供者

该包附带了一个用于Pimple的ServiceProvider,这是我最喜欢的独立PSR-11兼容容器。Pimple本身未列为require中的依赖(尽管它在require-dev中用于测试),因此如果你希望使用服务提供者,则需要直接将其添加到项目中。

composer require --prefer-dist pimple/pimple

由于服务提供者依赖于PSR-3 Logger,构建容器需要传递此参数

<?php

require_once __DIR__.'/../vendor/autoload.php';

use Monolog\Handler\StreamHandler;
use Psr\Log\LogLevel;
use Shrikeh\GuzzleMiddleware\TimerLogger\ServiceProvider\TimerLogger;

$logsPath = __DIR__.'/logs';
if (!is_dir($logsPath)) {
    mkdir($logsPath);
}

$logFile = new SplFileObject($logsPath.'/example.log', 'w+');

// create a log channel
$logger = new \Monolog\Logger('guzzle');
$logger->pushHandler(new StreamHandler(
    $logFile->getRealPath(),
    LogLevel::DEBUG
));

$pimple = new Pimple\Container();


// Create the middleware directly from an active instance of a LoggerInterface
$pimple->register(TimerLogger::fromLogger($logger));

$callable = function() use ($logFile) {
    $logger = new \Monolog\Logger('guzzle');
    $logger->pushHandler(new StreamHandler(
        $logFile->getRealPath(),
        LogLevel::DEBUG
    ));

    return $logger;
};

// Alternatively pass a simple callable to the static constructor
$pimple->register(TimerLogger::fromCallable($callable));

$someKeyForALogger = 'some_key_for_a_logger';

$pimple[$someKeyForALogger] = $callable;

$container = new Pimple\Psr11\Container($pimple);

// Or pass it a PSR-11 container and the key that will unwrap the PSR-3 LoggerInterface
$pimple->register(TimerLogger::fromContainer($container, $someKeyForALogger));

// The middleware is good to go.
echo get_class($pimple[TimerLogger::MIDDLEWARE]);