/modules/main/lib/diag/logformatter.php
PHP | 319 lines | 239 code | 32 blank | 48 comment | 25 complexity | 67c75835b6ebbcd9a21789c527f64923 MD5 | raw file
- <?php
- /**
- * Bitrix Framework
- * @package bitrix
- * @subpackage main
- * @copyright 2001-2021 Bitrix
- */
- namespace Bitrix\Main\Diag;
- use Bitrix\Main\Type;
- use Bitrix\Main\DB;
- class LogFormatter implements LogFormatterInterface
- {
- protected const DELIMITER = '----------';
- protected $showArguments;
- protected $argMaxChars;
- public function __construct($showArguments = false, $argMaxChars = 30)
- {
- $this->showArguments = $showArguments;
- $this->argMaxChars = $argMaxChars;
- }
- /**
- * Basic formatter to a string. Supports placeholders: {exception}, {trace}, {date}, {delimiter}.
- * @inheritDoc
- */
- public function format($message, array $context = []): string
- {
- // Implementors MAY have special handling for the passed objects. If that is not the case, implementors MUST cast it to a string.
- $message = $this->castToString($message);
- if (!isset($context['delimiter']))
- {
- $context['delimiter'] = static::DELIMITER;
- }
- // Placeholder names MUST be delimited with a single opening brace { and a single closing brace }. There MUST NOT be any whitespace between the delimiters and the placeholder name.
- $replace = [];
- foreach ($context as $key => $val)
- {
- $replace['{' . $key . '}'] = $this->castToString($val, $key);
- }
- return strtr($message, $replace);
- }
- /**
- * Magic is here.
- * @param mixed $value
- * @param null $placeholder
- * @return string
- */
- protected function castToString($value, $placeholder = null): string
- {
- if (!is_string($value))
- {
- if (is_object($value))
- {
- if ($placeholder == 'date' && $value instanceof Type\Date)
- {
- $value = $this->formatDate($value);
- }
- elseif ($placeholder == 'exception' && $value instanceof \Throwable)
- {
- $value = $this->formatException($value);
- }
- elseif (method_exists($value, '__toString'))
- {
- $value = (string)$value;
- }
- else
- {
- $value = $this->formatMixed($value);
- }
- }
- else
- {
- if ($placeholder == 'trace' && is_array($value))
- {
- $value = $this->formatTrace($value);
- }
- else
- {
- $value = $this->formatMixed($value);
- }
- }
- }
- return $value;
- }
- /**
- * Formats an exception.
- * @param \Throwable $exception
- * @return string
- */
- protected function formatException(\Throwable $exception): string
- {
- $result = '[' . get_class($exception) . '] ';
- if ($exception instanceof \ErrorException)
- {
- $result .= static::severityToString($exception->getSeverity());
- }
- $result .= "\n" . $exception->getMessage() . ' (' . $exception->getCode() . ')' . "\n";
- if ($exception instanceof DB\SqlQueryException)
- {
- $result .= $exception->getQuery() . "\n";
- }
- $file = $exception->getFile();
- if ($file)
- {
- $result .= $file . ':' . $exception->getLine() . "\n";
- }
- return $result;
- }
- /**
- * Formats a backtrace array.
- * @param array $trace
- * @return string
- */
- protected function formatTrace(array $trace): string
- {
- $result = '';
- foreach ($trace as $traceNum => $traceInfo)
- {
- $traceLine = '#'.$traceNum.': ';
- if (isset($traceInfo['class']))
- {
- $traceLine .= $traceInfo['class'] . $traceInfo['type'];
- }
- if (isset($traceInfo['function']))
- {
- $traceLine .= $traceInfo['function'];
- if(isset($traceInfo['args']))
- {
- $traceLine .= $this->formatArguments($traceInfo['args']);
- }
- }
- $traceLine .= "\n\t";
- if (isset($traceInfo['file']))
- {
- $traceLine .= $traceInfo['file'] . ':' . $traceInfo['line'];
- }
- $result .= $traceLine . "\n";
- }
- return $result;
- }
- /**
- * @internal
- * @param $args
- * @return string
- */
- public function formatArguments($args)
- {
- if ($args !== null)
- {
- $arguments = [];
- foreach ($args as $arg)
- {
- $arguments[] = $this->formatArgument($arg);
- }
- return '(' . implode(', ', $arguments) . ')';
- }
- return '()';
- }
- /**
- * @internal
- * @param $arg
- * @return array|string|string[]
- */
- public function formatArgument($arg)
- {
- if (!$this->showArguments)
- {
- return gettype($arg);
- }
- switch (gettype($arg))
- {
- case 'boolean':
- $result = $arg ? 'true' : 'false';
- break;
- case 'NULL':
- $result = 'null';
- break;
- case 'integer':
- case 'double':
- case 'float':
- $result = (string)$arg;
- break;
- case 'string':
- if (is_callable($arg, false, $callableName))
- {
- $result = 'fs:' . $callableName;
- }
- elseif (class_exists($arg, false))
- {
- $result = 'c:' . $arg;
- }
- elseif (interface_exists($arg, false))
- {
- $result = 'i:' . $arg;
- }
- else
- {
- if (mb_strlen($arg) > $this->argMaxChars)
- {
- $result = '"' . mb_substr($arg, 0, $this->argMaxChars / 2) . '...' . mb_substr($arg, -$this->argMaxChars / 2) . '" (' . mb_strlen($arg) . ')';
- }
- else
- {
- $result = '"' . $arg . '"';
- }
- }
- break;
- case 'array':
- if (is_callable($arg, false, $callableName))
- {
- $result = 'fa:' . $callableName;
- }
- else
- {
- $result = 'array(' . count($arg) . ')';
- }
- break;
- case 'object':
- $result = '[' . get_class($arg) . ']';
- break;
- case 'resource':
- $result = 'r:' . get_resource_type($arg);
- break;
- default:
- $result = 'unknown type';
- break;
- }
- return str_replace("\n", '\n', $result);
- }
- /**
- * Formats a date.
- * @param Type\DateTime $dateTime
- * @return string
- */
- protected function formatDate(Type\Date $dateTime): string
- {
- return $dateTime->format('Y-m-d H:i:s');
- }
- /**
- * Formats a mixed value.
- * @param mixed $value
- * @return string
- */
- protected function formatMixed($value): string
- {
- return var_export($value, true);
- }
- public static function severityToString($severity)
- {
- switch ($severity)
- {
- case 1:
- return 'E_ERROR';
- case 2:
- return 'E_WARNING';
- case 4:
- return 'E_PARSE';
- case 8:
- return 'E_NOTICE';
- case 16:
- return 'E_CORE_ERROR';
- case 32:
- return 'E_CORE_WARNING';
- case 64:
- return 'E_COMPILE_ERROR';
- case 128:
- return 'E_COMPILE_WARNING';
- case 256:
- return 'E_USER_ERROR';
- case 512:
- return 'E_USER_WARNING';
- case 1024:
- return 'E_USER_NOTICE';
- case 2048:
- return 'E_STRICT';
- case 4096:
- return 'E_RECOVERABLE_ERROR';
- case 8192:
- return 'E_DEPRECATED';
- case 16384:
- return 'E_USER_DEPRECATED';
- case 30719:
- return 'E_ALL';
- default:
- return 'UNKNOWN';
- }
- }
- }