123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- <?php
- /*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Symfony\Bridge\Monolog\Handler;
- use Monolog\Formatter\FormatterInterface;
- use Monolog\Handler\AbstractProcessingHandler;
- use Monolog\Handler\FormattableHandlerTrait;
- use Monolog\Logger;
- use Symfony\Bridge\Monolog\Formatter\VarDumperFormatter;
- if (trait_exists(FormattableHandlerTrait::class)) {
- class ServerLogHandler extends AbstractProcessingHandler
- {
- use ServerLogHandlerTrait;
- /**
- * {@inheritdoc}
- */
- protected function getDefaultFormatter(): FormatterInterface
- {
- return new VarDumperFormatter();
- }
- }
- } else {
- class ServerLogHandler extends AbstractProcessingHandler
- {
- use ServerLogHandlerTrait;
- /**
- * {@inheritdoc}
- */
- protected function getDefaultFormatter()
- {
- return new VarDumperFormatter();
- }
- }
- }
- /**
- * @author Grégoire Pineau <lyrixx@lyrixx.info>
- */
- trait ServerLogHandlerTrait
- {
- private $host;
- private $context;
- private $socket;
- /**
- * @param string|int $level The minimum logging level at which this handler will be triggered
- */
- public function __construct(string $host, $level = Logger::DEBUG, bool $bubble = true, array $context = [])
- {
- parent::__construct($level, $bubble);
- if (false === strpos($host, '://')) {
- $host = 'tcp://'.$host;
- }
- $this->host = $host;
- $this->context = stream_context_create($context);
- }
- /**
- * {@inheritdoc}
- */
- public function handle(array $record): bool
- {
- if (!$this->isHandling($record)) {
- return false;
- }
- set_error_handler(self::class.'::nullErrorHandler');
- try {
- if (!$this->socket = $this->socket ?: $this->createSocket()) {
- return false === $this->bubble;
- }
- } finally {
- restore_error_handler();
- }
- return parent::handle($record);
- }
- protected function write(array $record): void
- {
- $recordFormatted = $this->formatRecord($record);
- set_error_handler(self::class.'::nullErrorHandler');
- try {
- if (-1 === stream_socket_sendto($this->socket, $recordFormatted)) {
- stream_socket_shutdown($this->socket, \STREAM_SHUT_RDWR);
- // Let's retry: the persistent connection might just be stale
- if ($this->socket = $this->createSocket()) {
- stream_socket_sendto($this->socket, $recordFormatted);
- }
- }
- } finally {
- restore_error_handler();
- }
- }
- /**
- * {@inheritdoc}
- */
- protected function getDefaultFormatter(): FormatterInterface
- {
- return new VarDumperFormatter();
- }
- private static function nullErrorHandler()
- {
- }
- private function createSocket()
- {
- $socket = stream_socket_client($this->host, $errno, $errstr, 0, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT | \STREAM_CLIENT_PERSISTENT, $this->context);
- if ($socket) {
- stream_set_blocking($socket, false);
- }
- return $socket;
- }
- private function formatRecord(array $record): string
- {
- $recordFormatted = $record['formatted'];
- foreach (['log_uuid', 'uuid', 'uid'] as $key) {
- if (isset($record['extra'][$key])) {
- $recordFormatted['log_id'] = $record['extra'][$key];
- break;
- }
- }
- return base64_encode(serialize($recordFormatted))."\n";
- }
- }
|