Skip to content

Instantly share code, notes, and snippets.

@limingxinleo
Created November 12, 2021 11:28
Show Gist options
  • Select an option

  • Save limingxinleo/c8febbffe73af1c09a4a2b976500f806 to your computer and use it in GitHub Desktop.

Select an option

Save limingxinleo/c8febbffe73af1c09a4a2b976500f806 to your computer and use it in GitHub Desktop.
使用 Aspect 记录 RPC 调用日志
<?php
declare(strict_types=1);
use Hyperf\Di\Aop\AbstractAspect;
use Hyperf\Di\Aop\ProceedingJoinPoint;
use Hyperf\RpcClient\ServiceClient;
use Psr\EventDispatcher\EventDispatcherInterface;
class RPCAspect extends AbstractAspect
{
public $classes = [
ServiceClient::class . '::__call',
];
public function __construct(protected EventDispatcherInterface $dispatcher)
{
}
public function process(ProceedingJoinPoint $proceedingJoinPoint)
{
$beginTime = microtime(true);
$throwable = null;
$result = null;
try {
$result = $proceedingJoinPoint->process();
} catch (\Throwable $ex) {
$throwable = $ex;
}
try {
$method = $proceedingJoinPoint->arguments['keys']['method'] ?? '';
$params = $proceedingJoinPoint->arguments['keys']['params'] ?? [];
$service = $proceedingJoinPoint->getInstance()->getServiceName();
$time = microtime(true) - $beginTime;
$this->dispatcher->dispatch(new RPCEvent($service, $method, $params, $result, $time, $throwable));
} catch (\Throwable) {
}
return $result;
}
}
<?php
declare(strict_types=1);
use Throwable;
class RPCEvent
{
public function __construct(
public string $service,
public string $method,
public array $params,
public mixed $result,
public float $time,
public ?Throwable $throwable
) {
}
}
<?php
declare(strict_types=1);
use App\Constants\ErrorCode;
use App\Exception\BusinessException;
use Hyperf\Event\Contract\ListenerInterface;
use Hyperf\Logger\LoggerFactory;
use Hyperf\Utils\Codec\Json;
use Psr\Log\LoggerInterface;
class RPCEventListener implements ListenerInterface
{
protected LoggerInterface $logger;
public function __construct(LoggerFactory $factory)
{
$this->logger = $factory->get('rpc');
}
public function listen(): array
{
return [
RPCEvent::class,
];
}
public function process(object $event)
{
if ($event instanceof RPCEvent) {
if ($event->throwable) {
$this->logger->error($this->format($event));
throw new BusinessException(ErrorCode::SERVER_ERROR, '内部服务通信超时');
}
if ($event->time > 0.2) {
// 内部RPC请求,超过200ms时,记录日志
$this->logger->error($this->format($event));
} else {
$this->logger->info($this->format($event));
}
}
}
protected function format(RPCEvent $event): string
{
$result = $event->throwable ? ['rpc_failed' => true, 'message' => $event->throwable->getMessage()] : $event->result;
return Json::encode([
'service' => $event->service,
'method' => $event->method,
'params' => $event->params,
'result' => $result,
'time' => $event->time,
]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment