<?php
declare(strict_types=1);
namespace App\EventListener;
use App\Services\Metrics\MetricsAdapter;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\TerminateEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Throwable;
class ResponseTerminateListener implements EventSubscriberInterface
{
private const ACTIONS_BLACK_LIST = [
'GET /metrics',
'GET /robots.txt',
'POST /testHtml',
'GET /openapi/{fileSource}',
'GET /docs/file/{fileName}',
'GET /docs/{fileName}',
'GET /docs/',
'GET /.git/HEAD',
'GET /.git/config',
'GET /_wdt/aff0a1',
'GET /_wdt/635e7d',
'GET /_wdt/572ae2',
'GET /_wdt/2888d3',
'GET /_wdt/1a67b1',
'GET /_wdt/08f54a',
];
private const SUPPORTED_METHODS = [
Request::METHOD_GET,
Request::METHOD_POST,
Request::METHOD_PUT,
Request::METHOD_PATCH,
Request::METHOD_DELETE,
];
/**
* @var MetricsAdapter
*/
private $metricsAdapter;
public function __construct(MetricsAdapter $metricsAdapter)
{
$this->metricsAdapter = $metricsAdapter;
}
public function onKernelTerminate(TerminateEvent $event): void
{
try {
$path = rtrim($event->getRequest()->getPathInfo(), '/');
$method = $event->getRequest()->getMethod();
$action = $method . ' ' . $path;
$requestDuration = round((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']), 2); // in seconds
if (strlen($action) > 1 && in_array($method, self::SUPPORTED_METHODS) && !in_array($action, self::ACTIONS_BLACK_LIST)) {
$this->metricsAdapter->increaseRequestsMetric(['action' => $action, 'status' => $event->getResponse()->getStatusCode()]);
$this->metricsAdapter->increaseRequestDurationMetric($requestDuration, ['action' => $action, 'status' => $event->getResponse()->getStatusCode()]);
$this->metricsAdapter->setGaugeMetric('apcu_memory_usage', $this->getApcuMemUsage());
}
} catch (Throwable $e) {
}
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::TERMINATE => ['onKernelTerminate', -100],
];
}
private function getApcuMemUsage(): float
{
$mem = apcu_sma_info();
$memSize = $mem['num_seg'] * $mem['seg_size'];
$memAvail = $mem['avail_mem'];
$memUsed = $memSize - $memAvail;
// in Mb
for ($i = 0; $i < 2; $i++) {
$memUsed /= 1024;
}
return round($memUsed, 1);
}
}