Php 时间测量探查器服务使用什么设计模式?

Php 时间测量探查器服务使用什么设计模式?,php,symfony,design-patterns,Php,Symfony,Design Patterns,我有一个symfony2应用程序。它抽象了一组外部API,所有这些API都实现了externalapinterface 每个externalapinterface都有很多方法,例如fetchFoo和fetchBar 现在,我想编写一个服务来测量externalapinterface实例的每个方法调用的时间 我目前的想法是实现一个StopWatchExternalApiDecorator,它包装每个方法调用。然而,据我理解,这种方法会导致代码重复 我想我会使用时间测量,但这感觉很奇怪: class

我有一个symfony2应用程序。它抽象了一组外部API,所有这些API都实现了
externalapinterface

每个
externalapinterface
都有很多方法,例如
fetchFoo
fetchBar

现在,我想编写一个服务来测量
externalapinterface
实例的每个方法调用的时间

我目前的想法是实现一个
StopWatchExternalApiDecorator
,它包装每个方法调用。然而,据我理解,这种方法会导致代码重复

我想我会使用时间测量,但这感觉很奇怪:

class StopWatchExternalApiDecorator implements ExternalApiInterface {
    public function __construct(ExternalApiInterface $api, Stopwatch $stopWatch)
    {
       $this->api = $api;
       $this->stopWatch = $stopWatch;
    }

    public function fetchBar() {
         $this->stopWatch->start('fetchBar');
         $this->api->fetchBar()
         $this->stopWatch->stop('fetchBar');
    }

    public function fetchFoo() {
         $this->stopWatch->start('fetchFoo');
         $this->api->fetchFoo()
         $this->stopWatch->stop('fetchFoo');
    }
}
我似乎在伤害DNRY(不要重复你自己)的方法。我是在用正确的模式解决这类问题,还是有其他更合适的模式?更适合的含义是:一个地方进行所有测量,并且没有代码重复


我也不喜欢触摸装饰器,以防界面中出现新方法。在我看来,这应该是独立的。

我正在考虑我开发的一些API,它们使用一个通用函数进行调用和一个方法参数

下面是一些非常基本的伪代码

public function call($method = 'fetchBar',$params=array()){
    $this->stopWatch->start($method);
    $this->{"$method"}($params);
    $this->stopWatch->stop($method);

}

private function fetchBar(){
    echo "yo";
}

也许这会有所帮助

我正在考虑我开发的一些API,它们使用一个通用函数进行调用和一个方法参数

下面是一些非常基本的伪代码

public function call($method = 'fetchBar',$params=array()){
    $this->stopWatch->start($method);
    $this->{"$method"}($params);
    $this->stopWatch->stop($method);

}

private function fetchBar(){
    echo "yo";
}

也许这会有所帮助,我采用了装饰师的方法,只是在一个不同的层面上

在我的体系结构中,api服务使用的是
HttpClientInterface
,每个请求最后都通过调用
doRequest
来处理。因此,在没有代码重复的情况下,decorator最有意义:

<?php
namespace Kopernikus\BookingService\Component\Http\Client;

use Kopernikus\BookingService\Component\Performance\PerformanceEntry;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Stopwatch\Stopwatch;

/**
 * ProfileClientDecorator
 **/
class ProfileClientDecorator implements HttpClientInterface
{
    /**
     * @var Stopwatch
     */
    private $stopwatch;
    /**
     * @var HttpClientInterface
     */
    private $client;
    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * ProfileClientDecorator constructor.
     * @param HttpClientInterface $client
     * @param Stopwatch           $stopwatch
     * @param LoggerInterface     $logger
     */
    public function __construct(HttpClientInterface $client, Stopwatch $stopwatch, LoggerInterface $logger)
    {
        $this->client = $client;
        $this->stopwatch = $stopwatch;
        $this->logger = $logger;
    }

    /**
     * @param RequestInterface $request
     *
     * @return ResponseInterface
     */
    public function doRequest(RequestInterface $request)
    {
        $method =  $request->getMethod();
        $response = $this->doMeasuredRequest($request, $method);
        $performance = $this->getPerformance($method);
        $this->logPerformance($performance);

        return $response;
    }

    /**
     * @param RequestInterface $request
     * @param string           $method
     *
     * @return ResponseInterface
     */
    protected function doMeasuredRequest(RequestInterface $request, $method)
    {
        $this->stopwatch->start($method);
        $response = $this->client->doRequest($request);
        $this->stopwatch->stop($method);

        return $response;
    }

    /**
     * @param $method
     * @return PerformanceEntry
     */
    protected function getPerformance($method)
    {
        $event = $this->stopwatch->getEvent($method);
        $duration = $event->getDuration();

        return new PerformanceEntry($duration, $method);
    }

    /**
     * @param PerformanceEntry $performance
     */
    protected function logPerformance(PerformanceEntry $performance)
    {
        $context = [
            'performance' => [
                'duration_in_ms'       => $performance->getDurationInMs(),
                'request_name' => $performance->getRequestName(),
            ],
        ];

        $this->logger->info(
            "The request {$performance->getRequestName()} took {$performance->getDurationInMs()} ms",
            $context
        );
    }
}

我采用了装饰师的方法,只是在一个不同的层面上

在我的体系结构中,api服务使用的是
HttpClientInterface
,每个请求最后都通过调用
doRequest
来处理。因此,在没有代码重复的情况下,decorator最有意义:

<?php
namespace Kopernikus\BookingService\Component\Http\Client;

use Kopernikus\BookingService\Component\Performance\PerformanceEntry;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Stopwatch\Stopwatch;

/**
 * ProfileClientDecorator
 **/
class ProfileClientDecorator implements HttpClientInterface
{
    /**
     * @var Stopwatch
     */
    private $stopwatch;
    /**
     * @var HttpClientInterface
     */
    private $client;
    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * ProfileClientDecorator constructor.
     * @param HttpClientInterface $client
     * @param Stopwatch           $stopwatch
     * @param LoggerInterface     $logger
     */
    public function __construct(HttpClientInterface $client, Stopwatch $stopwatch, LoggerInterface $logger)
    {
        $this->client = $client;
        $this->stopwatch = $stopwatch;
        $this->logger = $logger;
    }

    /**
     * @param RequestInterface $request
     *
     * @return ResponseInterface
     */
    public function doRequest(RequestInterface $request)
    {
        $method =  $request->getMethod();
        $response = $this->doMeasuredRequest($request, $method);
        $performance = $this->getPerformance($method);
        $this->logPerformance($performance);

        return $response;
    }

    /**
     * @param RequestInterface $request
     * @param string           $method
     *
     * @return ResponseInterface
     */
    protected function doMeasuredRequest(RequestInterface $request, $method)
    {
        $this->stopwatch->start($method);
        $response = $this->client->doRequest($request);
        $this->stopwatch->stop($method);

        return $response;
    }

    /**
     * @param $method
     * @return PerformanceEntry
     */
    protected function getPerformance($method)
    {
        $event = $this->stopwatch->getEvent($method);
        $duration = $event->getDuration();

        return new PerformanceEntry($duration, $method);
    }

    /**
     * @param PerformanceEntry $performance
     */
    protected function logPerformance(PerformanceEntry $performance)
    {
        $context = [
            'performance' => [
                'duration_in_ms'       => $performance->getDurationInMs(),
                'request_name' => $performance->getRequestName(),
            ],
        ];

        $this->logger->info(
            "The request {$performance->getRequestName()} took {$performance->getDurationInMs()} ms",
            $context
        );
    }
}