src/ApiBundle/EventListeners/KernelListener.php line 42

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of the SynergyBot project.
  5.  *
  6.  * For the full copyright and license information,
  7.  * please read the LICENSE.md file that was distributed with this source code.
  8.  *
  9.  * The SymfonyBot project - inspiring people to chat!
  10.  *
  11.  * Copyright (c) 2022.
  12.  */
  13. namespace App\ApiBundle\EventListeners;
  14. use App\ApiBundle\Exception\ApiException;
  15. use App\ApiBundle\Response\ApiResponse;
  16. use App\ClickHouseBundle\Services\ClickHouseService;
  17. use App\CoreBundle\Util\Rand;
  18. use Psr\Log\LoggerAwareInterface;
  19. use Psr\Log\LoggerAwareTrait;
  20. use Symfony\Component\HttpFoundation\Response;
  21. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  22. use Symfony\Component\HttpKernel\Event\RequestEvent;
  23. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  24. class KernelListener implements LoggerAwareInterface
  25. {
  26.     use LoggerAwareTrait;
  27.     protected bool $isApiClient false;
  28.     protected bool $isApiPartner false;
  29.     protected bool $isApi false;
  30.     protected ?\Throwable $exception null;
  31.     public function __construct(
  32.         private readonly ClickHouseService $clickhouse)
  33.     {
  34.     }
  35.     public function onKernelRequest(RequestEvent $event)
  36.     {
  37.         $request $event->getRequest();
  38.         $route $request->get('_route');
  39.         $this->isApiClient null !== $route && (false !== mb_stripos((string) $route'api_client'));
  40.         $this->isApiPartner null !== $route && (false !== mb_stripos((string) $route'api_partner'));
  41.         $this->isApi $this->isApiClient || $this->isApiPartner;
  42.         if (!$this->isApi) {
  43.             return;
  44.         }
  45.         $request->request->add([
  46.             '_request_id' => Rand::getRandomSHA1(),
  47.         ]);
  48.     }
  49.     public function onKernelResponse(ResponseEvent $event)
  50.     {
  51.         if (!$this->isApi) {
  52.             return;
  53.         }
  54.         $request $event->getRequest();
  55.         $requestId $request->request->get('_request_id');
  56.         $request->request->remove('_request_id');
  57.         $requestParams implode(\PHP_EOL, [
  58.             'GET: '.http_build_query($request->query->all()),
  59.             'POST: '.http_build_query($request->request->all()),
  60.             'DATA: '.$request->getContent(),
  61.         ]);
  62.         $response $event->getResponse();
  63.         $currentAt = new \DateTime();
  64.         $exceptionText $this->exception $this->exception->__toString() : '';
  65.         $tableName $this->isApiClient 'client_api_logs' 'partner_api_logs';
  66.         $this->clickhouse->insert($tableName, [
  67.             [
  68.                 $requestId,
  69.                 $requestId,
  70.                 $currentAt->format('Y-m-d'),
  71.                 $currentAt->format('Y-m-d H:i:s'),
  72.                 $request->getClientIp(),
  73.                 $request->getUri(),
  74.                 $request->getMethod(),
  75.                 $response->getStatusCode(),
  76.                 $requestParams,
  77.                 $response->getContent() ?: '',
  78.                 $exceptionText,
  79.             ],
  80.         ], [
  81.             'request_id',
  82.             'queue_id',
  83.             'created_date',
  84.             'created_at',
  85.             'ip_addr',
  86.             'uri',
  87.             'method',
  88.             'status',
  89.             'request',
  90.             'response',
  91.             'exception',
  92.         ]);
  93.         $event->getResponse()->setStatusCode(200);
  94.     }
  95.     public function onKernelException(ExceptionEvent $event)
  96.     {
  97.         if (!$this->isApi) {
  98.             return;
  99.         }
  100.         $this->exception $event->getThrowable();
  101.         $status 0;
  102.         $message 'Try again later.';
  103.         $httpCode Response::HTTP_INTERNAL_SERVER_ERROR;
  104.         if ($this->exception instanceof ApiException) {
  105.             $status $this->exception->getCode();
  106.             $message $this->exception->getMessage();
  107.             $httpCode $this->exception->getStatusCode();
  108.             $this->logger->notice(
  109.                 'Api exception',
  110.                 [
  111.                     'code' => $status,
  112.                     'message' => $message,
  113.                     'http_code' => $httpCode,
  114.                     'exception' => $this->exception,
  115.                 ]
  116.             );
  117.         } else {
  118.             $this->logger->critical(
  119.                 'Kernel exception',
  120.                 [
  121.                     'code' => $this->exception->getCode(),
  122.                     'message' => $this->exception->getMessage(),
  123.                     'http_code' => $httpCode,
  124.                     'exception' => $this->exception,
  125.                 ]
  126.             );
  127.         }
  128.         $event->setResponse(new ApiResponse(
  129.             ['success' => false],
  130.             [
  131.                 'code' => $status,
  132.                 'message' => $message,
  133.             ],
  134.             $httpCode
  135.         ));
  136.         $event->getResponse()->setStatusCode($httpCode);
  137.     }
  138. }