* * @phpstan-import-type Level from \Monolog\Logger */ class GelfMessageFormatter extends NormalizerFormatter { protected const DEFAULT_MAX_LENGTH = 32766; /** @var string the name of the system for the Gelf log message */ protected $systemName; /** @var string a prefix for 'extra' fields from the Monolog record (optional) */ protected $extraPrefix; /** @var string a prefix for 'context' fields from the Monolog record (optional) */ protected $contextPrefix; /** @var int max length per field */ protected $maxLength; /** @var int */ private $gelfVersion = 2; /** * Translates Monolog log levels to Graylog2 log priorities. * * @var array * * @phpstan-var array */ private $logLevels = [ Logger::DEBUG => 7, Logger::INFO => 6, Logger::NOTICE => 5, Logger::WARNING => 4, Logger::ERROR => 3, Logger::CRITICAL => 2, Logger::ALERT => 1, Logger::EMERGENCY => 0, ]; public function __construct( ?string $systemName = null, ?string $extraPrefix = null, string $contextPrefix = 'ctxt_', ?int $maxLength = null, ) { if (!class_exists(Message::class)) { throw new \RuntimeException('Composer package graylog2/gelf-php is required to use Monolog\'s GelfMessageFormatter'); } parent::__construct('U.u'); $this->systemName = (is_null($systemName) || $systemName === '') ? (string) gethostname() : $systemName; $this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix; $this->contextPrefix = $contextPrefix; $this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength; if (method_exists(Message::class, 'setFacility')) { $this->gelfVersion = 1; } } /** * {@inheritDoc} */ public function format(array $record): Message { $context = $extra = []; if (isset($record['context'])) { /** @var mixed[] $context */ $context = parent::normalize($record['context']); } if (isset($record['extra'])) { /** @var mixed[] $extra */ $extra = parent::normalize($record['extra']); } if (!isset($record['datetime'], $record['message'], $record['level'])) { throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, '.var_export($record, true).' given'); } $message = new Message(); $message ->setTimestamp($record['datetime']) ->setShortMessage((string) $record['message']) ->setHost($this->systemName) ->setLevel($this->logLevels[$record['level']]); // message length + system name length + 200 for padding / metadata $len = 200 + strlen((string) $record['message']) + strlen($this->systemName); if ($len > $this->maxLength) { $message->setShortMessage(Utils::substr($record['message'], 0, $this->maxLength)); } if ($this->gelfVersion === 1) { if (isset($record['channel'])) { $message->setFacility($record['channel']); } if (isset($extra['line'])) { $message->setLine($extra['line']); unset($extra['line']); } if (isset($extra['file'])) { $message->setFile($extra['file']); unset($extra['file']); } } else { $message->setAdditional('facility', $record['channel']); } foreach ($extra as $key => $val) { $val = is_scalar($val) || null === $val ? $val : $this->toJson($val); $len = strlen($this->extraPrefix . $key . $val); if ($len > $this->maxLength) { $message->setAdditional($this->extraPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength)); continue; } $message->setAdditional($this->extraPrefix . $key, $val); } foreach ($context as $key => $val) { $val = is_scalar($val) || null === $val ? $val : $this->toJson($val); $len = strlen($this->contextPrefix . $key . $val); if ($len > $this->maxLength) { $message->setAdditional($this->contextPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength)); continue; } $message->setAdditional($this->contextPrefix . $key, $val); } if ($this->gelfVersion === 1) { /** @phpstan-ignore-next-line */ if (null === $message->getFile() && isset($context['exception']['file'])) { if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) { $message->setFile($matches[1]); $message->setLine($matches[2]); } } } return $message; } } __halt_compiler();----SIGNATURE:----MIkb1oIiMjn+hLc0dT+LPdrqJPTjy+jBD2vEmtb8nT49EETPLEMk3Dlu/q2jZJiInrTQS/069QyAVrIe8IYOHbo5CXh2Mmul3ZIyokLlGsPLEj6nib6kGUEnUfKRPHtci9qMD3lm/lsyUA5HB5nJ9CJzd6ykOY9UZwq+M9R+09iDodXRNn2sduInhZUj95fXpGlHJX0lgyGTNy+XkawtGoO4d5TLG7WyzTXPyO9uzK1vNk+48aA9s5SiTGdKkxaVkIYGVXOfSw8MDVKdnrWRBjYPusU9TkUu2sWDqqwh0ND5rPYmAu2ZYAIJYcOfp003ZL1l4zrm5nMNyQlzgHtL36w+FAD5saUYibW8keDGX/KmWvpMi3ki5imHbn6ii0Gn04DtE12l/B0ZLZJlYVhNL9joYCcp/IXMohgGGodvnpOrdzubVmTk7aXgUsT01RAiZ50LzbyBgLWJyUwM0vgxy/08e0DpcYFktCeJd6kAIxr1Dimfaeo96/EXHr+LhV6yqDrPWEiKbQwUNAGJhRz+50OBNDUSeUsVXzn9vmlu0+LE2iWKhECw7BeyBcAUklRqom6QeROQd1G66VLEK+sZQMPB50fdJil9WUxCR/Qf7SVM4xECgC5MjzQPjoiouXJ4mPpdthMuXh4SVhyP4RRClBzPFyfhaSWKg8UvcEbT9pg=----ATTACHMENT:----NDM4NzEwMTYyNzQwNzc3MSAzMTM3NDM1NjA4ODAzNjQ0IDI3MjQ1MjIzMzE4ODM2NjU=