diff --git a/src/Monolog/Formatter/LogglyFormatter.php b/src/Monolog/Formatter/LogglyFormatter.php new file mode 100644 index 00000000..46062aa9 --- /dev/null +++ b/src/Monolog/Formatter/LogglyFormatter.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * Extends the standard JsonFormatter to format messages compatible with Loggly. + * + * @author Adam Pancutt + */ +class LogglyFormatter extends JsonFormatter +{ + + /** + * {@inheritdoc} + */ + public function formatBatch(array $records) + { + $instance = $this; + + array_walk($records, function(&$value, $key) use ($instance) { + $value = $instance->format($value); + }); + + return implode("\n", $records); + } + +} diff --git a/src/Monolog/Handler/LogglyHandler.php b/src/Monolog/Handler/LogglyHandler.php index e0061a53..9a3de6e6 100644 --- a/src/Monolog/Handler/LogglyHandler.php +++ b/src/Monolog/Handler/LogglyHandler.php @@ -12,16 +12,19 @@ namespace Monolog\Handler; use Monolog\Logger; -use Monolog\Formatter\JsonFormatter; +use Monolog\Formatter\LogglyFormatter; /** * Sends errors to Loggly. * * @author Przemek Sobstel + * @author Adam Pancutt */ class LogglyHandler extends AbstractProcessingHandler { const HOST = 'logs-01.loggly.com'; + const ENDPOINT_SINGLE = 'inputs'; + const ENDPOINT_BATCH = 'bulk'; protected $token; @@ -45,17 +48,38 @@ class LogglyHandler extends AbstractProcessingHandler protected function write(array $record) { - $url = sprintf("http://%s/inputs/%s/", self::HOST, $this->token); + $this->send($record["formatted"], self::ENDPOINT_SINGLE); + } + + public function handleBatch(array $records) + { + $level = $this->level; + + $records = array_filter($records, function ($record) use ($level) { + return ($record['level'] >= $level); + }); + + if ($records) { + $this->send($this->getFormatter()->formatBatch($records), self::ENDPOINT_BATCH); + } + } + + protected function send($data, $endpoint) + { + $url = sprintf("https://%s/%s/%s/", self::HOST, $endpoint, $this->token); + + $headers = array('Content-Type: application/json'); + if ($this->tag) { - $url .= sprintf("tag/%s/", $this->tag); + $headers[] = "X-LOGGLY-TAG: {$this->tag}"; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, $record["formatted"]); - curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_exec($ch); @@ -64,6 +88,6 @@ class LogglyHandler extends AbstractProcessingHandler protected function getDefaultFormatter() { - return new JsonFormatter(); + return new LogglyFormatter(); } } diff --git a/tests/Monolog/Formatter/LogglyFormatterTest.php b/tests/Monolog/Formatter/LogglyFormatterTest.php new file mode 100644 index 00000000..a6d8d57a --- /dev/null +++ b/tests/Monolog/Formatter/LogglyFormatterTest.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; +use Monolog\TestCase; + +class LogglyFormatterTest extends TestCase +{ + + /** + * @covers Monolog\Formatter\LogglyFormatter::formatBatch + */ + public function testFormatBatch() + { + $formatter = new LogglyFormatter(); + $records = $expected = array( + $this->getRecord(Logger::WARNING), + $this->getRecord(Logger::DEBUG), + ); + array_walk($expected, function(&$value, $key) { + $value = json_encode($value); + }); + $this->assertEquals(implode("\n", $expected), $formatter->formatBatch($records)); + } + +}