vendor/symfony/monolog-bridge/Handler/ServerLogHandler.php line 22

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Bridge\Monolog\Handler;
  11. use Monolog\Formatter\FormatterInterface;
  12. use Monolog\Handler\AbstractHandler;
  13. use Monolog\Logger;
  14. use Symfony\Bridge\Monolog\Formatter\VarDumperFormatter;
  15. /**
  16.  * @author GrĂ©goire Pineau <lyrixx@lyrixx.info>
  17.  */
  18. class ServerLogHandler extends AbstractHandler
  19. {
  20.     private $host;
  21.     private $context;
  22.     private $socket;
  23.     /**
  24.      * @param string|int $level The minimum logging level at which this handler will be triggered
  25.      */
  26.     public function __construct(string $host$level Logger::DEBUGbool $bubble true, array $context = [])
  27.     {
  28.         parent::__construct($level$bubble);
  29.         if (false === strpos($host'://')) {
  30.             $host 'tcp://'.$host;
  31.         }
  32.         $this->host $host;
  33.         $this->context stream_context_create($context);
  34.     }
  35.     /**
  36.      * {@inheritdoc}
  37.      *
  38.      * @return bool
  39.      */
  40.     public function handle(array $record)
  41.     {
  42.         if (!$this->isHandling($record)) {
  43.             return false;
  44.         }
  45.         set_error_handler(self::class.'::nullErrorHandler');
  46.         try {
  47.             if (!$this->socket $this->socket ?: $this->createSocket()) {
  48.                 return false === $this->bubble;
  49.             }
  50.         } finally {
  51.             restore_error_handler();
  52.         }
  53.         $recordFormatted $this->formatRecord($record);
  54.         set_error_handler(self::class.'::nullErrorHandler');
  55.         try {
  56.             if (-=== stream_socket_sendto($this->socket$recordFormatted)) {
  57.                 stream_socket_shutdown($this->socket, \STREAM_SHUT_RDWR);
  58.                 // Let's retry: the persistent connection might just be stale
  59.                 if ($this->socket $this->createSocket()) {
  60.                     stream_socket_sendto($this->socket$recordFormatted);
  61.                 }
  62.             }
  63.         } finally {
  64.             restore_error_handler();
  65.         }
  66.         return false === $this->bubble;
  67.     }
  68.     /**
  69.      * {@inheritdoc}
  70.      *
  71.      * @return FormatterInterface
  72.      */
  73.     protected function getDefaultFormatter()
  74.     {
  75.         return new VarDumperFormatter();
  76.     }
  77.     private static function nullErrorHandler()
  78.     {
  79.     }
  80.     private function createSocket()
  81.     {
  82.         $socket stream_socket_client($this->host$errno$errstr0, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT | \STREAM_CLIENT_PERSISTENT$this->context);
  83.         if ($socket) {
  84.             stream_set_blocking($socketfalse);
  85.         }
  86.         return $socket;
  87.     }
  88.     private function formatRecord(array $record): string
  89.     {
  90.         if ($this->processors) {
  91.             foreach ($this->processors as $processor) {
  92.                 $record $processor($record);
  93.             }
  94.         }
  95.         $recordFormatted $this->getFormatter()->format($record);
  96.         foreach (['log_uuid''uuid''uid'] as $key) {
  97.             if (isset($record['extra'][$key])) {
  98.                 $recordFormatted['log_id'] = $record['extra'][$key];
  99.                 break;
  100.             }
  101.         }
  102.         return base64_encode(serialize($recordFormatted))."\n";
  103.     }
  104. }