Просмотр исходного кода

Merge remote-tracking branch 'pomaxa/master'

Jordi Boggiano 13 лет назад
Родитель
Сommit
efa37359df

+ 4 - 0
README.mdown

@@ -111,6 +111,9 @@ Handlers
 - _GelfHandler_: Logs records to a [Graylog2](http://www.graylog2.org) server.
 - _SocketHandler_: Logs records to [sockets](http://php.net/fsockopen), use this
   for UNIX and TCP sockets. See an [example](https://github.com/Seldaek/monolog/blob/master/doc/sockets.md).
+- _AmqpHandler_L Logs records using [amqp](php.net/manual/en/book.amqp.php) protocol to the RabbitMQ server.
+  Note: handler needs an installed amqp version > 1.
+  For instructions on installation look in (http://lv.php.net/manual/en/amqp.installation.php)
 
 Wrappers / Special Handlers
 ---------------------------
@@ -161,6 +164,7 @@ Requirements
 
 - Any flavor of PHP 5.3 should do
 - [optional] PHPUnit 3.5+ to execute the test suite (phpunit --version)
+- [optional] installed amqp library to use AmqpHandler.
 
 Submitting bugs and feature requests
 ------------------------------------

+ 67 - 0
src/Monolog/Handler/AmqpHandler.php

@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Monolog\Logger;
+use Monolog\Formatter\JsonFormatter;
+
+class AmqpHandler extends AbstractProcessingHandler
+{
+    /**
+     * @var \AMQPExchange $exchange
+     */
+    protected $exchange;
+
+    /**
+     * @param \AMQPExchange $exchange AMQP exchange, ready for use
+     * @param string $exchangeName
+     * @param string $issuer isser name
+     * @param int $level
+     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+     */
+    public function __construct(\AMQPExchange $exchange, $exchangeName = 'log', $level = Logger::DEBUG, $bubble = true)
+    {
+        $this->exchange = $exchange;
+        $this->exchange->setName($exchangeName);
+
+        parent::__construct($level, $bubble);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function write(array $record)
+    {
+        $data = $record["formatted"];
+
+        $routingKey = sprintf('%s.%s',
+            substr($record['level_name'], 0, 4),
+            $record['channel']);
+
+        //we do not check return value because no handler really does
+        $this->exchange->publish($data,
+            strtolower($routingKey),
+            0,
+            array(
+                'delivery_mode' => 2,
+                'Content-type' => 'application/json'
+            ));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected function getDefaultFormatter()
+    {
+        return new JsonFormatter();
+    }
+}

+ 29 - 0
tests/Monolog/Handler/AmqpExchangeMock.php

@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+class MockAMQPExchange extends \AMQPExchange
+{
+    public function __construct()
+    {
+    }
+
+    public function publish($message, $routing_key, $params = 0, $attributes = array())
+    {
+        return true;
+    }
+
+    public function setName($name)
+    {
+        return true;
+    }
+}

+ 61 - 0
tests/Monolog/Handler/AmqpHandlerTest.php

@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Monolog package.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Monolog\TestCase;
+use Monolog\Logger;
+use Monolog\Handler\MockAMQPExchange;
+
+/**
+ * @covers Monolog\Handler\RotatingFileHandler
+ */
+class AmqpHandlerTest extends TestCase
+{
+    public function setUp()
+    {
+        if (!class_exists('AMQPConnection') || !class_exists('AMQPExchange')) {
+            $this->markTestSkipped("amqp-php not installed");
+        }
+
+        if (!class_exists('AMQPChannel')) {
+            $this->markTestSkipped("Please update AMQP to version >= 1");
+        }
+    }
+
+    public function testHandle()
+    {
+        $exchange = $this->getExchange();
+
+        $handler = new AmqpHandler($exchange, 'log');
+
+        $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));
+
+        $handler->handle($record);
+    }
+
+    protected function getExchange()
+    {
+        /* sorry, but PHP bug in zend_object_store_get_object segfaults
+        php where using mocks on AMQP classes. should be fixed someday,
+        but now it's time for some shitcode (see below)
+        $exchange = $this->getMockBuilder('\AMQPExchange')
+            ->setConstructorArgs(array($this->getMock('\AMQPChannel')))
+            ->setMethods(array('setName'))
+            ->getMock();
+
+        $exchange->expects($this->any())
+            ->method('setName')
+            ->will($this->returnValue(true));
+        */
+        return new MockAMQPExchange();
+    }
+}