diff --git a/.travis.yml b/.travis.yml index dbb2084a..9cfc502a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,13 @@ language: php sudo: false +dist: trusty + +php: + - 7.0 + - 7.1 + - hhvm + - nightly cache: directories: @@ -10,9 +17,6 @@ matrix: include: - php: 7.0 env: deps=low - - php: 7.0 - - php: 7.1 - - php: nightly fast_finish: true allow_failures: - php: nightly diff --git a/src/Monolog/Formatter/GelfMessageFormatter.php b/src/Monolog/Formatter/GelfMessageFormatter.php index d6d46c05..4e95a6e4 100644 --- a/src/Monolog/Formatter/GelfMessageFormatter.php +++ b/src/Monolog/Formatter/GelfMessageFormatter.php @@ -22,7 +22,7 @@ use Gelf\Message; */ class GelfMessageFormatter extends NormalizerFormatter { - const MAX_LENGTH = 32766; + const DEFAULT_MAX_LENGTH = 32766; /** * @var string the name of the system for the Gelf log message @@ -39,6 +39,11 @@ class GelfMessageFormatter extends NormalizerFormatter */ protected $contextPrefix; + /** + * @var int max length per field + */ + protected $maxLength; + /** * Translates Monolog log levels to Graylog2 log priorities. */ @@ -53,7 +58,7 @@ class GelfMessageFormatter extends NormalizerFormatter Logger::EMERGENCY => 0, ]; - public function __construct(string $systemName = null, string $extraPrefix = null, string $contextPrefix = 'ctxt_') + public function __construct(string $systemName = null, string $extraPrefix = null, string $contextPrefix = 'ctxt_', int $maxLength = null) { parent::__construct('U.u'); @@ -61,6 +66,7 @@ class GelfMessageFormatter extends NormalizerFormatter $this->extraPrefix = $extraPrefix; $this->contextPrefix = $contextPrefix; + $this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength; } /** @@ -86,35 +92,30 @@ class GelfMessageFormatter extends NormalizerFormatter ->setHost($this->systemName) ->setLevel($this->logLevels[$record['level']]); - // start count with message length + system name length + 200 for padding / metadata + // message length + system name length + 200 for padding / metadata $len = 200 + strlen((string) $record['message']) + strlen($this->systemName); - if ($len > self::MAX_LENGTH) { - $message->setShortMessage(substr($record['message'], 0, self::MAX_LENGTH - 200)); - - return $message; + if ($len > $this->maxLength) { + $message->setShortMessage(substr($record['message'], 0, $this->maxLength)); } if (isset($record['channel'])) { $message->setFacility($record['channel']); - $len += strlen($record['channel']); } if (isset($record['extra']['line'])) { $message->setLine($record['extra']['line']); - $len += 10; unset($record['extra']['line']); } if (isset($record['extra']['file'])) { $message->setFile($record['extra']['file']); - $len += strlen($record['extra']['file']); unset($record['extra']['file']); } foreach ($record['extra'] as $key => $val) { $val = is_scalar($val) || null === $val ? $val : $this->toJson($val); - $len += strlen($this->extraPrefix . $key . $val); - if ($len > self::MAX_LENGTH) { - $message->setAdditional($this->extraPrefix . $key, substr($val, 0, self::MAX_LENGTH - $len)); + $len = strlen($this->extraPrefix . $key . $val); + if ($len > $this->maxLength) { + $message->setAdditional($this->extraPrefix . $key, substr($val, 0, $this->maxLength)); break; } $message->setAdditional($this->extraPrefix . $key, $val); @@ -122,9 +123,9 @@ class GelfMessageFormatter extends NormalizerFormatter foreach ($record['context'] as $key => $val) { $val = is_scalar($val) || null === $val ? $val : $this->toJson($val); - $len += strlen($this->contextPrefix . $key . $val); - if ($len > self::MAX_LENGTH) { - $message->setAdditional($this->contextPrefix . $key, substr($val, 0, self::MAX_LENGTH - $len)); + $len = strlen($this->contextPrefix . $key . $val); + if ($len > $this->maxLength) { + $message->setAdditional($this->contextPrefix . $key, substr($val, 0, $this->maxLength)); break; } $message->setAdditional($this->contextPrefix . $key, $val); diff --git a/src/Monolog/Formatter/JsonFormatter.php b/src/Monolog/Formatter/JsonFormatter.php index 61ccf2ca..8e2f2fdd 100644 --- a/src/Monolog/Formatter/JsonFormatter.php +++ b/src/Monolog/Formatter/JsonFormatter.php @@ -27,6 +27,7 @@ class JsonFormatter extends NormalizerFormatter protected $batchMode; protected $appendNewline; + /** * @var bool */ @@ -81,9 +82,6 @@ class JsonFormatter extends NormalizerFormatter } } - /** - * @param bool $include - */ public function includeStacktraces(bool $include = true) { $this->includeStacktraces = $include; diff --git a/tests/Monolog/Formatter/GelfMessageFormatterTest.php b/tests/Monolog/Formatter/GelfMessageFormatterTest.php index 15d9bda8..958883f2 100644 --- a/tests/Monolog/Formatter/GelfMessageFormatterTest.php +++ b/tests/Monolog/Formatter/GelfMessageFormatterTest.php @@ -221,10 +221,34 @@ class GelfMessageFormatterTest extends \PHPUnit_Framework_TestCase } } - // in graylog2/gelf-php before 1.4.1 empty strings are filtered and won't be included in the message - // though it should be sufficient to ensure that the entire message length does not exceed the maximum - // length being allowed - $this->assertLessThanOrEqual(32766, $length, 'The message length is no longer than the maximum allowed length'); + $this->assertLessThanOrEqual(65792, $length, 'The message length is no longer than the maximum allowed length'); + } + + public function testFormatWithUnlimitedLength() + { + $formatter = new GelfMessageFormatter(null, null, 'ctxt_', PHP_INT_MAX); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('exception' => str_repeat(' ', 32767 * 2)), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => str_repeat(' ', 32767 * 2)), + 'message' => 'log' + ); + $message = $formatter->format($record); + $messageArray = $message->toArray(); + + // 200 for padding + metadata + $length = 200; + + foreach ($messageArray as $key => $value) { + if (!in_array($key, array('level', 'timestamp'))) { + $length += strlen($value); + } + } + + $this->assertGreaterThanOrEqual(131289, $length, 'The message should not be truncated'); } private function isLegacy()