From 486cbb78abcd5e7ebed799b98725826df036023b Mon Sep 17 00:00:00 2001 From: Pablo Belloc Date: Sat, 25 Feb 2012 20:37:04 -0300 Subject: [PATCH 01/13] Initial version --- src/Monolog/Handler/SocketHandler.php | 65 +++++++ .../Exception/ConnectionException.php | 10 + .../Exception/WriteToSocketException.php | 11 ++ .../Handler/SocketHandler/MockSocket.php | 60 ++++++ .../SocketHandler/PersistentSocket.php | 24 +++ src/Monolog/Handler/SocketHandler/Socket.php | 178 ++++++++++++++++++ .../Handler/SocketHandler/SocketTest.php | 114 +++++++++++ tests/Monolog/Handler/SocketHandlerTest.php | 54 ++++++ 8 files changed, 516 insertions(+) create mode 100644 src/Monolog/Handler/SocketHandler.php create mode 100644 src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php create mode 100644 src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php create mode 100644 src/Monolog/Handler/SocketHandler/MockSocket.php create mode 100644 src/Monolog/Handler/SocketHandler/PersistentSocket.php create mode 100644 src/Monolog/Handler/SocketHandler/Socket.php create mode 100644 tests/Monolog/Handler/SocketHandler/SocketTest.php create mode 100644 tests/Monolog/Handler/SocketHandlerTest.php diff --git a/src/Monolog/Handler/SocketHandler.php b/src/Monolog/Handler/SocketHandler.php new file mode 100644 index 00000000..c778da2f --- /dev/null +++ b/src/Monolog/Handler/SocketHandler.php @@ -0,0 +1,65 @@ + + */ + +namespace Monolog\Handler; + +use Monolog\Handler\SocketHandler\Socket; +use Monolog\Handler\SocketHandler\PersistentSocket; +use Monolog\Logger; + +/** + * Stores to any socket - uses fsockopen() or pfsockopen(). + * + * @see Monolog\Handler\SocketHandler\Socket + * @see Monolog\Handler\SocketHandler\PersistentSocket + * @see http://php.net/manual/en/function.fsockopen.php + */ +class SocketHandler extends AbstractProcessingHandler +{ + /** + * @var Socket + */ + private $socket; + + /** + * @param string $connectionString + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + $this->socket = new Socket($connectionString); + } + + /** + * Inject socket - allows you to configure timeouts. + * + * @param Socket $socket + */ + public function setSocket(Socket $socket) + { + $this->socket = $socket; + } + + /** + * We will not close a PersistentSocket instance so it can be reused in other requests. + */ + public function close() + { + if ($this->socket instanceof PersistentSocket) { + return; + } + $this->socket->close(); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $this->socket->write((string) $record['formatted']); + } +} diff --git a/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php b/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php new file mode 100644 index 00000000..c43541c4 --- /dev/null +++ b/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php @@ -0,0 +1,10 @@ + + */ + +namespace Monolog\Handler\SocketHandler\Exception; + +class ConnectionException extends \RuntimeException +{ +} \ No newline at end of file diff --git a/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php b/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php new file mode 100644 index 00000000..4843f2e6 --- /dev/null +++ b/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php @@ -0,0 +1,11 @@ + + */ + + +namespace Monolog\Handler\SocketHandler\Exception; + +class WriteToSocketException extends \RuntimeException +{ +} \ No newline at end of file diff --git a/src/Monolog/Handler/SocketHandler/MockSocket.php b/src/Monolog/Handler/SocketHandler/MockSocket.php new file mode 100644 index 00000000..885ffabb --- /dev/null +++ b/src/Monolog/Handler/SocketHandler/MockSocket.php @@ -0,0 +1,60 @@ + + */ + + +namespace Monolog\Handler\SocketHandler; + +use Monolog\Handler\SocketHandler\Exception\ConnectionException; +use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; + +class MockSocket extends Socket +{ + private $connectTimeoutMock = 0; + private $timeoutMock = 0; + + + public function __construct($connectionString) + { + if (is_resource($connectionString)) { + $this->resource = $connectionString; + } else { + $this->connectionString = $connectionString; + } + } + + public function setFailConnectionTimeout($seconds) + { + $this->connectTimeoutMock = (int)$seconds; + } + + public function setFailTimeout($seconds) + { + $this->timeoutMock = (int)$seconds; + } + + protected function createSocketResource() + { + if ($this->connectTimeoutMock > 0) { + throw new ConnectionException("Mocked connection timeout"); + } + $this->resource = fopen('php://memory', '+a'); + } + + protected function writeToSocket($data) { + if ($this->timeoutMock > 0) { + throw new WriteToSocketException("Mocked write timeout"); + } + return parent::writeToSocket($data); + } + + protected function setSocketTimeout() + { + // php://memory does not support this + } + + public function getResource() { + return $this->resource; + } +} diff --git a/src/Monolog/Handler/SocketHandler/PersistentSocket.php b/src/Monolog/Handler/SocketHandler/PersistentSocket.php new file mode 100644 index 00000000..9facb40e --- /dev/null +++ b/src/Monolog/Handler/SocketHandler/PersistentSocket.php @@ -0,0 +1,24 @@ + + */ + +namespace Monolog\Handler\SocketHandler; + +use Monolog\Handler\SocketHandler\Exception\ConnectionException; + +/** + * Same as Socket but uses pfsockopen() instead allowing the connection to be reused in other requests. + * + * @see http://php.net/manual/en/function.pfsockopen.php + */ +class PersistentSocket extends Socket +{ + protected function createSocketResource() { + @$resource = pfsockopen($this->connectionString, -1, $errno, $errstr, $this->connectionTimeout); + if (!$resource) { + throw new ConnectionException("Failed connecting to $this->connectionString ($errno: $errstr)"); + } + $this->resource = $resource; + } +} diff --git a/src/Monolog/Handler/SocketHandler/Socket.php b/src/Monolog/Handler/SocketHandler/Socket.php new file mode 100644 index 00000000..ede89f54 --- /dev/null +++ b/src/Monolog/Handler/SocketHandler/Socket.php @@ -0,0 +1,178 @@ + + */ + +namespace Monolog\Handler\SocketHandler; + +use Monolog\Handler\SocketHandler\Exception\ConnectionException; +use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; + +/** + * Small class which writes to a socket. + * Timeout settings must be set before first write to have any effect. + * + * @see http://php.net/manual/en/function.fsockopen.php + */ +class Socket +{ + protected $connectionString; + protected $connectionTimeout; + protected $resource; + private $timeout = 0; + + /** + * @param string $connectionString As interpreted by fsockopen() + */ + public function __construct($connectionString) + { + $this->connectionString = $connectionString; + $this->connectionTimeout = (float)ini_get('default_socket_timeout'); + } + + public function getConnectionString() + { + return $this->connectionString; + } + + /** + * Set connection timeout. Only has effect before we connect. + * + * @see http://php.net/manual/en/function.fsockopen.php + * @param integer $seconds + */ + public function setConnectionTimeout($seconds) + { + $this->validateTimeout($seconds); + $this->connectionTimeout = (float)$seconds; + } + + /** + * Set write timeout. Only has effect before we connect. + * + * @see http://php.net/manual/en/function.stream-set-timeout.php + * @param type $seconds + */ + public function setTimeout($seconds) + { + $this->validateTimeout($seconds); + $this->timeout = (int)$seconds; + } + + private function validateTimeout($value) + { + $ok = filter_var($value, FILTER_VALIDATE_INT, array('options' => array( + 'min_range' => 0, + ))); + if ($ok === false) { + throw new \InvalidArgumentException("Timeout must be 0 or a positive integer (got $value)"); + } + } + + public function getConnectionTimeout() { + return $this->connectionTimeout; + } + + public function getTimeout() { + return $this->timeout; + } + + public function close() + { + if (is_resource($this->resource)) { + fclose($this->resource); + $this->resource = null; + } + } + + /** + * Allow injecting a resource opened somewhere else. Used in tests. + * + * @throws \InvalidArgumentException + * @param resource $resource + */ + public function setResource($resource) + { + if (is_resource($resource)) { + $this->resource = $resource; + } else { + throw new \InvalidArgumentException("Expected a resource"); + } + } + + /** + * Connect (if necessary) and write to the socket + * + * @throws Monolog\Handler\SocketHandler\Exception\ConnectionException + * @throws Monolog\Handler\SocketHandler\Exception\WriteToSocketException + * @param string $string + */ + public function write($string) + { + $this->connectIfNotConnected(); + $this->writeToSocket($string); + } + + protected function connectIfNotConnected() + { + if ($this->isConnected()) { + return; + } + $this->connect(); + } + + /** + * Check to see if the socket is currently available. + * + * UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details. + * + * @return boolean + */ + public function isConnected() + { + return is_resource($this->resource) + && !feof($this->resource); // on TCP - other party can close connection. + } + + protected function connect() + { + $this->createSocketResource(); + $this->setSocketTimeout(); + } + + protected function createSocketResource() + { + @$resource = fsockopen($this->connectionString, -1, $errno, $errstr, $this->connectionTimeout); + if (!$resource) { + throw new ConnectionException("Failed connecting to $this->connectionString ($errno: $errstr)"); + } + $this->resource = $resource; + } + + protected function setSocketTimeout() + { + if (!stream_set_timeout($this->resource, $this->timeout)) { + throw new ConnectionException("Failed setting timeout with stream_set_timeout()"); + } + } + + protected function writeToSocket($data) + { + $length = strlen($data); + $sent = 0; + while ($this->isConnected() && $sent < $length) { + @$chunk = fwrite($this->resource, substr($data, $sent)); + if ($chunk === false) { + throw new WriteToSocketException("Could not write to socket"); + } + $sent += $chunk; + $socketInfo = stream_get_meta_data($this->resource); + if ($socketInfo['timed_out']) { + throw new WriteToSocketException("Write timed-out"); + } + } + if (!$this->isConnected() && $sent < $length) { + throw new WriteToSocketException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); + } + } +} diff --git a/tests/Monolog/Handler/SocketHandler/SocketTest.php b/tests/Monolog/Handler/SocketHandler/SocketTest.php new file mode 100644 index 00000000..7e12cbb6 --- /dev/null +++ b/tests/Monolog/Handler/SocketHandler/SocketTest.php @@ -0,0 +1,114 @@ +write('data'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testBadConnectionTimeout() + { + $socket = new Socket('localhost:1234'); + $socket->setConnectionTimeout(-1); + } + + public function testSetConnectionTimeout() + { + $socket = new Socket('localhost:1234'); + $socket->setConnectionTimeout(10); + $this->assertEquals(10, $socket->getConnectionTimeout()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testBadTimeout() + { + $socket = new Socket('localhost:1234'); + $socket->setTimeout(-1); + } + + public function testSetTimeout() + { + $socket = new Socket('localhost:1234'); + $socket->setTimeout(10); + $this->assertEquals(10, $socket->getTimeout()); + } + + public function testSetConnectionString() + { + $socket = new Socket('tcp://localhost:9090'); + $this->assertEquals('tcp://localhost:9090', $socket->getConnectionString()); + } + + public function testConnectionRefuesed() + { + try { + $socket = new Socket('127.0.0.1:7894'); + $socket->setTimeout(1); + $string = 'Hello world'; + $socket->write($string); + $this->fail("Shoul not connect - are you running a server on 127.0.0.1:7894 ?"); + } catch (\Monolog\Handler\SocketHandler\Exception\ConnectionException $e) { + } + } + + /** + * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException + */ + public function testConnectionTimeoutWithMock() + { + $socket = new MockSocket('localhost:54321'); + $socket->setConnectionTimeout(10); + $socket->setFailConnectionTimeout(10); + $socket->write('Hello world'); + } + + /** + * @expectedException Monolog\Handler\SocketHandler\Exception\WriteToSocketException + */ + public function testWriteTimeoutWithMock() + { + $socket = new MockSocket('localhost:54321'); + $socket->setTimeout(10); + $socket->setFailTimeout(10); + $socket->write('Hello world'); + } + + public function testWriteWithMock() + { + $socket = new MockSocket('localhost:54321'); + $socket->write('Hello world'); + $res = $socket->getResource(); + fseek($res, 0); + $this->assertEquals('Hello world', fread($res, 1024)); + } + + public function testClose() + { + $resource = fopen('php://memory', 'a+'); + $socket = new MockSocket($resource); + $this->assertTrue(is_resource($resource)); + $socket->close(); + $this->assertFalse(is_resource($resource)); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testInjectBadResourceThrowsException() + { + $socket = new Socket(''); + $socket->setResource(''); + } +} \ No newline at end of file diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php new file mode 100644 index 00000000..69eb3d71 --- /dev/null +++ b/tests/Monolog/Handler/SocketHandlerTest.php @@ -0,0 +1,54 @@ + + */ + + +namespace Monolog\Handler; + +use Monolog\Handler\SocketHandler\MockSocket; +use Monolog\Handler\SocketHandler\Socket; +use Monolog\Handler\SocketHandler\PersistentSocket; + +use Monolog\TestCase; +use Monolog\Logger; + +class SocketHandlerTest extends TestCase +{ + public function testWrite() + { + $socket = new MockSocket('localhost'); + $handler = new SocketHandler('localhost'); + $handler->setSocket($socket); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord(Logger::WARNING, 'test')); + $handler->handle($this->getRecord(Logger::WARNING, 'test2')); + $handler->handle($this->getRecord(Logger::WARNING, 'test3')); + $handle = $socket->getResource(); + fseek($handle, 0); + $this->assertEquals('testtest2test3', fread($handle, 100)); + } + + public function testCloseClosesNonPersistentSocket() + { + $socket = new Socket('localhost'); + $res = fopen('php://memory', 'a'); + $socket->setResource($res); + $handler = new SocketHandler('localhost'); + $handler->setSocket($socket); + $handler->close(); + $this->assertFalse($socket->isConnected()); + } + + public function testCloseDoesNotClosePersistentSocket() + { + $socket = new PersistentSocket('localhost'); + $res = fopen('php://memory', 'a'); + $socket->setResource($res); + $handler = new SocketHandler('localhost'); + $handler->setSocket($socket); + $handler->close(); + $this->assertTrue($socket->isConnected()); + } + +} From d75e0b73f38ad4c1d6bd61166140e237dea70cb4 Mon Sep 17 00:00:00 2001 From: Pablo Belloc Date: Sat, 25 Feb 2012 21:37:53 -0300 Subject: [PATCH 02/13] Add some documentation --- README.mdown | 1 + doc/sockets.md | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 doc/sockets.md diff --git a/README.mdown b/README.mdown index 516c6513..9a19ac29 100644 --- a/README.mdown +++ b/README.mdown @@ -45,6 +45,7 @@ Handlers - _NativeMailHandler_: Sends emails using PHP's mail() function. - _SwiftMailerHandler_: Sends emails using a SwiftMailer instance. - _SyslogHandler_: Logs records to the syslog. +- _SocketHandler_: Logs records to [sockets](http://php.net/fsockopen), use this for UNIX and TCP sockets. See an [example](https://github.com/pablolb/monolog/blob/master/doc/sockets.md). Wrappers / Special Handlers --------------------------- diff --git a/doc/sockets.md b/doc/sockets.md new file mode 100644 index 00000000..287db3f0 --- /dev/null +++ b/doc/sockets.md @@ -0,0 +1,84 @@ +Sockets Handler +=============== + +This handler allows you to write your logs to sockets using [fsockopen](http://php.net/fsockopen) +or [pfsockopen](http://php.net/pfsockopen). + +Basic Example +------------- + +This example e persistent connections: + +```php +pushHandler($handler, Logger::DEBUG); + +// You can now use your logger +$logger->addInfo('My logger is now ready'); + +``` + +In this example, using syslog-ng, you should see the log on the log server: + + cweb1 [2012-02-26 00:12:03] my_logger.INFO: My logger is now ready [] [] + + +Symfony2 Example +---------------- + +In Symfony2, first we have to create the handler service in our services.xml (or similar): + +```xml + + + %logging.socket.connection_string% + + 2 + + + 2 + + + + + + + + + + +``` + +And then, change our config.yml (or similar): + +```yaml +parameters: + logging.socket.connection_string: 'unix:///var/log/httpd_app_log.socket' + +monolog: + handlers: + main: + type: stream + path: %kernel.logs_dir%/%kernel.environment%.log + level: debug + firephp: + type: firephp + level: info + custom: + type: service + id: logging.socket_handler +``` From 423cfebf94df25f993978e76e5300b1bafbd55a7 Mon Sep 17 00:00:00 2001 From: Pablo Belloc Date: Sat, 25 Feb 2012 23:36:07 -0300 Subject: [PATCH 03/13] Add license header and move @author to phpdoc --- .../Exception/ConnectionException.php | 10 ++++++++-- .../Exception/WriteToSocketException.php | 11 ++++++++--- src/Monolog/Handler/SocketHandler/MockSocket.php | 11 ++++++++--- .../Handler/SocketHandler/PersistentSocket.php | 14 +++++++++++--- src/Monolog/Handler/SocketHandler/Socket.php | 11 +++++++++-- .../Monolog/Handler/SocketHandler/SocketTest.php | 10 ++++++++++ tests/Monolog/Handler/SocketHandlerTest.php | 16 +++++++++++++--- 7 files changed, 67 insertions(+), 16 deletions(-) diff --git a/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php b/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php index c43541c4..fd183687 100644 --- a/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php +++ b/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php @@ -1,6 +1,12 @@ + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Monolog\Handler\SocketHandler\Exception; diff --git a/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php b/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php index 4843f2e6..c03c1b63 100644 --- a/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php +++ b/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php @@ -1,8 +1,13 @@ - */ +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace Monolog\Handler\SocketHandler\Exception; diff --git a/src/Monolog/Handler/SocketHandler/MockSocket.php b/src/Monolog/Handler/SocketHandler/MockSocket.php index 885ffabb..2826433d 100644 --- a/src/Monolog/Handler/SocketHandler/MockSocket.php +++ b/src/Monolog/Handler/SocketHandler/MockSocket.php @@ -1,8 +1,13 @@ - */ +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace Monolog\Handler\SocketHandler; diff --git a/src/Monolog/Handler/SocketHandler/PersistentSocket.php b/src/Monolog/Handler/SocketHandler/PersistentSocket.php index 9facb40e..c4a2d788 100644 --- a/src/Monolog/Handler/SocketHandler/PersistentSocket.php +++ b/src/Monolog/Handler/SocketHandler/PersistentSocket.php @@ -1,6 +1,12 @@ + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Monolog\Handler\SocketHandler; @@ -11,10 +17,12 @@ use Monolog\Handler\SocketHandler\Exception\ConnectionException; * Same as Socket but uses pfsockopen() instead allowing the connection to be reused in other requests. * * @see http://php.net/manual/en/function.pfsockopen.php + * @author Pablo de Leon Belloc */ class PersistentSocket extends Socket { - protected function createSocketResource() { + protected function createSocketResource() + { @$resource = pfsockopen($this->connectionString, -1, $errno, $errstr, $this->connectionTimeout); if (!$resource) { throw new ConnectionException("Failed connecting to $this->connectionString ($errno: $errstr)"); diff --git a/src/Monolog/Handler/SocketHandler/Socket.php b/src/Monolog/Handler/SocketHandler/Socket.php index ede89f54..281d162f 100644 --- a/src/Monolog/Handler/SocketHandler/Socket.php +++ b/src/Monolog/Handler/SocketHandler/Socket.php @@ -1,6 +1,12 @@ + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Monolog\Handler\SocketHandler; @@ -13,6 +19,7 @@ use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; * Timeout settings must be set before first write to have any effect. * * @see http://php.net/manual/en/function.fsockopen.php + * @author Pablo de Leon Belloc */ class Socket { diff --git a/tests/Monolog/Handler/SocketHandler/SocketTest.php b/tests/Monolog/Handler/SocketHandler/SocketTest.php index 7e12cbb6..cc5b237a 100644 --- a/tests/Monolog/Handler/SocketHandler/SocketTest.php +++ b/tests/Monolog/Handler/SocketHandler/SocketTest.php @@ -1,5 +1,15 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + + namespace Monolog\Handler\SocketHandler; class SocketTest extends \PHPUnit_Framework_TestCase diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php index 69eb3d71..cc5c9201 100644 --- a/tests/Monolog/Handler/SocketHandlerTest.php +++ b/tests/Monolog/Handler/SocketHandlerTest.php @@ -1,8 +1,13 @@ - */ +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace Monolog\Handler; @@ -13,6 +18,11 @@ use Monolog\Handler\SocketHandler\PersistentSocket; use Monolog\TestCase; use Monolog\Logger; + + +/** + * @author Pablo de Leon Belloc + */ class SocketHandlerTest extends TestCase { public function testWrite() From d752f435b502f0a09e4db71d7b99fff2b73db403 Mon Sep 17 00:00:00 2001 From: Pablo Belloc Date: Sun, 26 Feb 2012 11:45:10 -0300 Subject: [PATCH 04/13] Remove Socket, PeristentSocket and MockSocket classes --- src/Monolog/Handler/SocketHandler.php | 203 ++++++++++++-- .../Handler/SocketHandler/MockSocket.php | 65 ----- .../SocketHandler/PersistentSocket.php | 32 --- src/Monolog/Handler/SocketHandler/Socket.php | 185 ------------- .../Handler/SocketHandler/SocketTest.php | 116 -------- tests/Monolog/Handler/SocketHandlerTest.php | 262 +++++++++++++++--- 6 files changed, 410 insertions(+), 453 deletions(-) delete mode 100644 src/Monolog/Handler/SocketHandler/MockSocket.php delete mode 100644 src/Monolog/Handler/SocketHandler/PersistentSocket.php delete mode 100644 src/Monolog/Handler/SocketHandler/Socket.php diff --git a/src/Monolog/Handler/SocketHandler.php b/src/Monolog/Handler/SocketHandler.php index c778da2f..32a9295d 100644 --- a/src/Monolog/Handler/SocketHandler.php +++ b/src/Monolog/Handler/SocketHandler.php @@ -5,24 +5,24 @@ namespace Monolog\Handler; -use Monolog\Handler\SocketHandler\Socket; -use Monolog\Handler\SocketHandler\PersistentSocket; use Monolog\Logger; +use Monolog\Handler\SocketHandler\Exception\ConnectionException; +use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; + /** * Stores to any socket - uses fsockopen() or pfsockopen(). * - * @see Monolog\Handler\SocketHandler\Socket - * @see Monolog\Handler\SocketHandler\PersistentSocket * @see http://php.net/manual/en/function.fsockopen.php */ class SocketHandler extends AbstractProcessingHandler { - /** - * @var Socket - */ - private $socket; - + private $connectionString; + private $connectionTimeout; + private $resource; + private $timeout = 0; + private $persistent = false; + /** * @param string $connectionString * @param integer $level The minimum logging level at which this handler will be triggered @@ -31,17 +31,21 @@ class SocketHandler extends AbstractProcessingHandler public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true) { parent::__construct($level, $bubble); - $this->socket = new Socket($connectionString); + $this->connectionString = $connectionString; + $this->connectionTimeout = (float)ini_get('default_socket_timeout'); } - + /** - * Inject socket - allows you to configure timeouts. + * Connect (if necessary) and write to the socket * - * @param Socket $socket + * @throws Monolog\Handler\SocketHandler\Exception\ConnectionException + * @throws Monolog\Handler\SocketHandler\Exception\WriteToSocketException + * @param string $string */ - public function setSocket(Socket $socket) + public function write(array $record) { - $this->socket = $socket; + $this->connectIfNotConnected(); + $this->writeToSocket((string) $record['formatted']); } /** @@ -49,17 +53,172 @@ class SocketHandler extends AbstractProcessingHandler */ public function close() { - if ($this->socket instanceof PersistentSocket) { + if ($this->isPersistent()) { return; } - $this->socket->close(); + $this->closeSocket(); + } + + public function closeSocket() + { + if (is_resource($this->resource)) { + fclose($this->resource); + $this->resource = null; + } + } + + public function setPersistent($boolean) + { + $this->persistent = (boolean)$boolean; + } + + /** + * Set connection timeout. Only has effect before we connect. + * + * @see http://php.net/manual/en/function.fsockopen.php + * @param integer $seconds + */ + public function setConnectionTimeout($seconds) + { + $this->validateTimeout($seconds); + $this->connectionTimeout = (float)$seconds; + } + + /** + * Set write timeout. Only has effect before we connect. + * + * @see http://php.net/manual/en/function.stream-set-timeout.php + * @param type $seconds + */ + public function setTimeout($seconds) + { + $this->validateTimeout($seconds); + $this->timeout = (int)$seconds; + } + + private function validateTimeout($value) + { + $ok = filter_var($value, FILTER_VALIDATE_INT, array('options' => array( + 'min_range' => 0, + ))); + if ($ok === false) { + throw new \InvalidArgumentException("Timeout must be 0 or a positive integer (got $value)"); + } + } + + public function getConnectionString() + { + return $this->connectionString; + } + + public function isPersistent() + { + return $this->persistent; + } + + public function getConnectionTimeout() { + return $this->connectionTimeout; + } + + public function getTimeout() { + return $this->timeout; + } + + /** + * Allow injecting a resource opened somewhere else. Used in tests. + * + * @throws \InvalidArgumentException + * @param resource $resource + */ + public function setResource($resource) + { + if (is_resource($resource)) { + $this->resource = $resource; + } else { + throw new \InvalidArgumentException("Expected a resource"); + } } - /** - * {@inheritdoc} - */ - protected function write(array $record) + private function connectIfNotConnected() { - $this->socket->write((string) $record['formatted']); + if ($this->isConnected()) { + return; + } + $this->connect(); + } + + /** + * Check to see if the socket is currently available. + * + * UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details. + * + * @return boolean + */ + public function isConnected() + { + return is_resource($this->resource) + && !feof($this->resource); // on TCP - other party can close connection. + } + + private function connect() + { + $this->createSocketResource(); + $this->setSocketTimeout(); + } + + protected function createSocketResource() + { + if ($this->persistent) { + @$resource = pfsockopen($this->connectionString, -1, $errno, $errstr, $this->connectionTimeout); + } else { + @$resource = fsockopen($this->connectionString, -1, $errno, $errstr, $this->connectionTimeout); + } + if (!$resource) { + throw new ConnectionException("Failed connecting to $this->connectionString ($errno: $errstr)"); + } + $this->resource = $resource; + } + + private function setSocketTimeout() + { + if (!stream_set_timeout($this->resource, $this->timeout)) { + throw new ConnectionException("Failed setting timeout with stream_set_timeout()"); + } + } + + protected function writeToSocket($data) + { + $length = strlen($data); + $sent = 0; + while ($this->isConnected() && $sent < $length) { + $chunk = $this->fwrite(substr($data, $sent)); + if ($chunk === false) { + throw new WriteToSocketException("Could not write to socket"); + } + $sent += $chunk; + $socketInfo = $this->stream_get_meta_data(); + if ($socketInfo['timed_out']) { + throw new WriteToSocketException("Write timed-out"); + } + } + if (!$this->isConnected() && $sent < $length) { + throw new WriteToSocketException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); + } + } + + /** + * Allow mock + */ + protected function fwrite($data) + { + return @fwrite($this->resource, $data); + } + + /** + * Allow mock + */ + protected function stream_get_meta_data() + { + return stream_get_meta_data($this->resource); } } diff --git a/src/Monolog/Handler/SocketHandler/MockSocket.php b/src/Monolog/Handler/SocketHandler/MockSocket.php deleted file mode 100644 index 2826433d..00000000 --- a/src/Monolog/Handler/SocketHandler/MockSocket.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Monolog\Handler\SocketHandler; - -use Monolog\Handler\SocketHandler\Exception\ConnectionException; -use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; - -class MockSocket extends Socket -{ - private $connectTimeoutMock = 0; - private $timeoutMock = 0; - - - public function __construct($connectionString) - { - if (is_resource($connectionString)) { - $this->resource = $connectionString; - } else { - $this->connectionString = $connectionString; - } - } - - public function setFailConnectionTimeout($seconds) - { - $this->connectTimeoutMock = (int)$seconds; - } - - public function setFailTimeout($seconds) - { - $this->timeoutMock = (int)$seconds; - } - - protected function createSocketResource() - { - if ($this->connectTimeoutMock > 0) { - throw new ConnectionException("Mocked connection timeout"); - } - $this->resource = fopen('php://memory', '+a'); - } - - protected function writeToSocket($data) { - if ($this->timeoutMock > 0) { - throw new WriteToSocketException("Mocked write timeout"); - } - return parent::writeToSocket($data); - } - - protected function setSocketTimeout() - { - // php://memory does not support this - } - - public function getResource() { - return $this->resource; - } -} diff --git a/src/Monolog/Handler/SocketHandler/PersistentSocket.php b/src/Monolog/Handler/SocketHandler/PersistentSocket.php deleted file mode 100644 index c4a2d788..00000000 --- a/src/Monolog/Handler/SocketHandler/PersistentSocket.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Monolog\Handler\SocketHandler; - -use Monolog\Handler\SocketHandler\Exception\ConnectionException; - -/** - * Same as Socket but uses pfsockopen() instead allowing the connection to be reused in other requests. - * - * @see http://php.net/manual/en/function.pfsockopen.php - * @author Pablo de Leon Belloc - */ -class PersistentSocket extends Socket -{ - protected function createSocketResource() - { - @$resource = pfsockopen($this->connectionString, -1, $errno, $errstr, $this->connectionTimeout); - if (!$resource) { - throw new ConnectionException("Failed connecting to $this->connectionString ($errno: $errstr)"); - } - $this->resource = $resource; - } -} diff --git a/src/Monolog/Handler/SocketHandler/Socket.php b/src/Monolog/Handler/SocketHandler/Socket.php deleted file mode 100644 index 281d162f..00000000 --- a/src/Monolog/Handler/SocketHandler/Socket.php +++ /dev/null @@ -1,185 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Monolog\Handler\SocketHandler; - -use Monolog\Handler\SocketHandler\Exception\ConnectionException; -use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; - -/** - * Small class which writes to a socket. - * Timeout settings must be set before first write to have any effect. - * - * @see http://php.net/manual/en/function.fsockopen.php - * @author Pablo de Leon Belloc - */ -class Socket -{ - protected $connectionString; - protected $connectionTimeout; - protected $resource; - private $timeout = 0; - - /** - * @param string $connectionString As interpreted by fsockopen() - */ - public function __construct($connectionString) - { - $this->connectionString = $connectionString; - $this->connectionTimeout = (float)ini_get('default_socket_timeout'); - } - - public function getConnectionString() - { - return $this->connectionString; - } - - /** - * Set connection timeout. Only has effect before we connect. - * - * @see http://php.net/manual/en/function.fsockopen.php - * @param integer $seconds - */ - public function setConnectionTimeout($seconds) - { - $this->validateTimeout($seconds); - $this->connectionTimeout = (float)$seconds; - } - - /** - * Set write timeout. Only has effect before we connect. - * - * @see http://php.net/manual/en/function.stream-set-timeout.php - * @param type $seconds - */ - public function setTimeout($seconds) - { - $this->validateTimeout($seconds); - $this->timeout = (int)$seconds; - } - - private function validateTimeout($value) - { - $ok = filter_var($value, FILTER_VALIDATE_INT, array('options' => array( - 'min_range' => 0, - ))); - if ($ok === false) { - throw new \InvalidArgumentException("Timeout must be 0 or a positive integer (got $value)"); - } - } - - public function getConnectionTimeout() { - return $this->connectionTimeout; - } - - public function getTimeout() { - return $this->timeout; - } - - public function close() - { - if (is_resource($this->resource)) { - fclose($this->resource); - $this->resource = null; - } - } - - /** - * Allow injecting a resource opened somewhere else. Used in tests. - * - * @throws \InvalidArgumentException - * @param resource $resource - */ - public function setResource($resource) - { - if (is_resource($resource)) { - $this->resource = $resource; - } else { - throw new \InvalidArgumentException("Expected a resource"); - } - } - - /** - * Connect (if necessary) and write to the socket - * - * @throws Monolog\Handler\SocketHandler\Exception\ConnectionException - * @throws Monolog\Handler\SocketHandler\Exception\WriteToSocketException - * @param string $string - */ - public function write($string) - { - $this->connectIfNotConnected(); - $this->writeToSocket($string); - } - - protected function connectIfNotConnected() - { - if ($this->isConnected()) { - return; - } - $this->connect(); - } - - /** - * Check to see if the socket is currently available. - * - * UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details. - * - * @return boolean - */ - public function isConnected() - { - return is_resource($this->resource) - && !feof($this->resource); // on TCP - other party can close connection. - } - - protected function connect() - { - $this->createSocketResource(); - $this->setSocketTimeout(); - } - - protected function createSocketResource() - { - @$resource = fsockopen($this->connectionString, -1, $errno, $errstr, $this->connectionTimeout); - if (!$resource) { - throw new ConnectionException("Failed connecting to $this->connectionString ($errno: $errstr)"); - } - $this->resource = $resource; - } - - protected function setSocketTimeout() - { - if (!stream_set_timeout($this->resource, $this->timeout)) { - throw new ConnectionException("Failed setting timeout with stream_set_timeout()"); - } - } - - protected function writeToSocket($data) - { - $length = strlen($data); - $sent = 0; - while ($this->isConnected() && $sent < $length) { - @$chunk = fwrite($this->resource, substr($data, $sent)); - if ($chunk === false) { - throw new WriteToSocketException("Could not write to socket"); - } - $sent += $chunk; - $socketInfo = stream_get_meta_data($this->resource); - if ($socketInfo['timed_out']) { - throw new WriteToSocketException("Write timed-out"); - } - } - if (!$this->isConnected() && $sent < $length) { - throw new WriteToSocketException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); - } - } -} diff --git a/tests/Monolog/Handler/SocketHandler/SocketTest.php b/tests/Monolog/Handler/SocketHandler/SocketTest.php index cc5b237a..a7b1d49f 100644 --- a/tests/Monolog/Handler/SocketHandler/SocketTest.php +++ b/tests/Monolog/Handler/SocketHandler/SocketTest.php @@ -1,124 +1,8 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - - namespace Monolog\Handler\SocketHandler; class SocketTest extends \PHPUnit_Framework_TestCase { - /** - * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException - */ - public function testInvalidHostname() { - $socket = new Socket('garbage://here'); - $socket->write('data'); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testBadConnectionTimeout() - { - $socket = new Socket('localhost:1234'); - $socket->setConnectionTimeout(-1); - } - - public function testSetConnectionTimeout() - { - $socket = new Socket('localhost:1234'); - $socket->setConnectionTimeout(10); - $this->assertEquals(10, $socket->getConnectionTimeout()); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testBadTimeout() - { - $socket = new Socket('localhost:1234'); - $socket->setTimeout(-1); - } - - public function testSetTimeout() - { - $socket = new Socket('localhost:1234'); - $socket->setTimeout(10); - $this->assertEquals(10, $socket->getTimeout()); - } - - public function testSetConnectionString() - { - $socket = new Socket('tcp://localhost:9090'); - $this->assertEquals('tcp://localhost:9090', $socket->getConnectionString()); - } - - public function testConnectionRefuesed() - { - try { - $socket = new Socket('127.0.0.1:7894'); - $socket->setTimeout(1); - $string = 'Hello world'; - $socket->write($string); - $this->fail("Shoul not connect - are you running a server on 127.0.0.1:7894 ?"); - } catch (\Monolog\Handler\SocketHandler\Exception\ConnectionException $e) { - } - } - - /** - * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException - */ - public function testConnectionTimeoutWithMock() - { - $socket = new MockSocket('localhost:54321'); - $socket->setConnectionTimeout(10); - $socket->setFailConnectionTimeout(10); - $socket->write('Hello world'); - } - - /** - * @expectedException Monolog\Handler\SocketHandler\Exception\WriteToSocketException - */ - public function testWriteTimeoutWithMock() - { - $socket = new MockSocket('localhost:54321'); - $socket->setTimeout(10); - $socket->setFailTimeout(10); - $socket->write('Hello world'); - } - - public function testWriteWithMock() - { - $socket = new MockSocket('localhost:54321'); - $socket->write('Hello world'); - $res = $socket->getResource(); - fseek($res, 0); - $this->assertEquals('Hello world', fread($res, 1024)); - } - - public function testClose() - { - $resource = fopen('php://memory', 'a+'); - $socket = new MockSocket($resource); - $this->assertTrue(is_resource($resource)); - $socket->close(); - $this->assertFalse(is_resource($resource)); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testInjectBadResourceThrowsException() - { - $socket = new Socket(''); - $socket->setResource(''); - } } \ No newline at end of file diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php index cc5c9201..97a69e09 100644 --- a/tests/Monolog/Handler/SocketHandlerTest.php +++ b/tests/Monolog/Handler/SocketHandlerTest.php @@ -11,54 +11,250 @@ namespace Monolog\Handler; -use Monolog\Handler\SocketHandler\MockSocket; -use Monolog\Handler\SocketHandler\Socket; -use Monolog\Handler\SocketHandler\PersistentSocket; - use Monolog\TestCase; use Monolog\Logger; - - +use Monolog\Handler\SocketHandler\Exception\ConnectionException; +use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; /** * @author Pablo de Leon Belloc */ class SocketHandlerTest extends TestCase { - public function testWrite() - { - $socket = new MockSocket('localhost'); - $handler = new SocketHandler('localhost'); - $handler->setSocket($socket); - $handler->setFormatter($this->getIdentityFormatter()); - $handler->handle($this->getRecord(Logger::WARNING, 'test')); - $handler->handle($this->getRecord(Logger::WARNING, 'test2')); - $handler->handle($this->getRecord(Logger::WARNING, 'test3')); - $handle = $socket->getResource(); - fseek($handle, 0); - $this->assertEquals('testtest2test3', fread($handle, 100)); + /** + * @var Monolog\Handler\SocketHandler + */ + private $handler; + + /** + * @var resource + */ + private $res; + + /** + * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException + */ + public function testInvalidHostname() { + $this->createHandler('garbage://here'); + $this->writeRecord('data'); } - public function testCloseClosesNonPersistentSocket() + /** + * @expectedException \InvalidArgumentException + */ + public function testBadConnectionTimeout() { - $socket = new Socket('localhost'); - $res = fopen('php://memory', 'a'); - $socket->setResource($res); - $handler = new SocketHandler('localhost'); - $handler->setSocket($socket); - $handler->close(); - $this->assertFalse($socket->isConnected()); + $this->createHandler('localhost:1234'); + $this->handler->setConnectionTimeout(-1); + } + + public function testSetConnectionTimeout() + { + $this->createHandler('localhost:1234'); + $this->handler->setConnectionTimeout(10); + $this->assertEquals(10, $this->handler->getConnectionTimeout()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testBadTimeout() + { + $this->createHandler('localhost:1234'); + $this->handler->setTimeout(-1); + } + + public function testSetTimeout() + { + $this->createHandler('localhost:1234'); + $this->handler->setTimeout(10); + $this->assertEquals(10, $this->handler->getTimeout()); + } + + public function testSetConnectionString() + { + $this->createHandler('tcp://localhost:9090'); + $this->assertEquals('tcp://localhost:9090', $this->handler->getConnectionString()); + } + + public function testConnectionRefuesed() + { + try { + $this->createHandler('127.0.0.1:7894'); + $string = 'Hello world'; + $this->writeRecord($string); + $this->fail("Shoul not connect - are you running a server on 127.0.0.1:7894 ?"); + } catch (\Monolog\Handler\SocketHandler\Exception\ConnectionException $e) { + } + } + + /** + * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException + */ + public function testConnectionTimeoutWithMock() + { + $this->setMockHandler(array('createSocketResource')); + $this->handler->expects($this->once()) + ->method('createSocketResource') + ->will($this->throwException(new ConnectionException())); + $this->writeRecord('Hello world'); + } + + /** + * @expectedException Monolog\Handler\SocketHandler\Exception\WriteToSocketException + */ + public function testWriteFailsOnIfFwriteReturnsFalse() + { + $this->setMockHandler(array('fwrite')); + + $map = array( + array('Hello world', 6), + array('world', false), + ); + + $this->handler->expects($this->exactly(2)) + ->method('fwrite') + ->will($this->returnValueMap($map)); + + $this->injectMemoryResource(); + $this->writeRecord('Hello world'); + } + + /** + * @expectedException Monolog\Handler\SocketHandler\Exception\WriteToSocketException + */ + public function testWriteFailsIfStreamTimesOut() + { + $this->setMockHandler(array('fwrite', 'stream_get_meta_data')); + + $map = array( + array('Hello world', 6), + array('world', 5), + ); + + $this->handler->expects($this->exactly(1)) + ->method('fwrite') + ->will($this->returnValueMap($map)); + $this->handler->expects($this->exactly(1)) + ->method('stream_get_meta_data') + ->will($this->returnValue(array('timed_out' => true))); + + + $this->injectMemoryResource(); + $this->writeRecord('Hello world'); + } + + /** + * @expectedException Monolog\Handler\SocketHandler\Exception\WriteToSocketException + */ + public function testWriteFailsOnIncompleteWrite() + { + $this->setMockHandler(array('fwrite', 'isConnected')); + + $map = array( + array('Hello world', 6), + array('world', 5), + ); + + $this->handler->expects($this->exactly(1)) + ->method('fwrite') + ->will($this->returnValueMap($map)); + $this->handler->expects($this->at(0)) + ->method('isConnected') + ->will($this->returnValue(true)); + $this->handler->expects($this->at(1)) + ->method('isConnected') + ->will($this->returnValue(true)); + $this->handler->expects($this->at(2)) + ->method('isConnected') + ->will($this->returnValue(false)); + + $this->injectMemoryResource(); + $this->writeRecord('Hello world'); + } + + public function testWriteWithMemoryFile() + { + $this->createHandler('localhost:54321'); + $this->injectMemoryResource(); + $this->writeRecord('test1'); + $this->writeRecord('test2'); + $this->writeRecord('test3'); + fseek($this->res, 0); + $this->assertEquals('test1test2test3', fread($this->res, 1024)); + } + + public function testWriteWithMock() + { + $this->setMockHandler(array('fwrite')); + + $map = array( + array('Hello world', 6), + array('world', 5), + ); + + $this->handler->expects($this->exactly(2)) + ->method('fwrite') + ->will($this->returnValueMap($map)); + + $this->injectMemoryResource(); + $this->writeRecord('Hello world'); + } + + public function testClose() + { + $this->createHandler('localhost:54321'); + $this->injectMemoryResource(); + $this->writeRecord('Hello world'); + $this->assertTrue(is_resource($this->res)); + $this->handler->close(); + $this->assertFalse(is_resource($this->res)); } public function testCloseDoesNotClosePersistentSocket() { - $socket = new PersistentSocket('localhost'); - $res = fopen('php://memory', 'a'); - $socket->setResource($res); - $handler = new SocketHandler('localhost'); - $handler->setSocket($socket); - $handler->close(); - $this->assertTrue($socket->isConnected()); + $this->createHandler('localhost:54321'); + $this->handler->setPersistent(true); + $this->injectMemoryResource(); + $this->writeRecord('Hello world'); + $this->assertTrue(is_resource($this->res)); + $this->handler->close(); + $this->assertTrue(is_resource($this->res)); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testInjectBadResourceThrowsException() + { + $this->createHandler(''); + $this->handler->setResource(''); } + private function createHandler($connectionString) + { + $this->handler = new SocketHandler($connectionString); + $this->handler->setFormatter($this->getIdentityFormatter()); + } + + private function writeRecord($string) + { + $this->handler->handle($this->getRecord(Logger::WARNING, $string)); + } + + private function injectMemoryResource() + { + $this->res = fopen('php://memory', 'a'); + $this->handler->setResource($this->res); + } + + private function setMockHandler(array $methods) + { + $this->handler = $this->getMock( + '\Monolog\Handler\SocketHandler', + $methods, + array('localhost:1234') + ); + $this->handler->setFormatter($this->getIdentityFormatter()); + } } From ff287b9d10071513b006f193d188e847d4a5a95f Mon Sep 17 00:00:00 2001 From: Pablo Belloc Date: Sun, 26 Feb 2012 11:58:10 -0300 Subject: [PATCH 05/13] Fix docs --- README.mdown | 2 +- doc/sockets.md | 50 +------------------------------------------------- 2 files changed, 2 insertions(+), 50 deletions(-) diff --git a/README.mdown b/README.mdown index 9a19ac29..30ffc597 100644 --- a/README.mdown +++ b/README.mdown @@ -45,7 +45,7 @@ Handlers - _NativeMailHandler_: Sends emails using PHP's mail() function. - _SwiftMailerHandler_: Sends emails using a SwiftMailer instance. - _SyslogHandler_: Logs records to the syslog. -- _SocketHandler_: Logs records to [sockets](http://php.net/fsockopen), use this for UNIX and TCP sockets. See an [example](https://github.com/pablolb/monolog/blob/master/doc/sockets.md). +- _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). Wrappers / Special Handlers --------------------------- diff --git a/doc/sockets.md b/doc/sockets.md index 287db3f0..98acfdab 100644 --- a/doc/sockets.md +++ b/doc/sockets.md @@ -14,13 +14,13 @@ This example e persistent connections: use Monolog\Logger; use Monolog\Handler\SocketHandler; -use Monolog\Handler\SocketHandler\Socket; // Create the logger $logger = new Logger('my_logger'); // Create the handler $handler = new SocketHandler('unix:///var/log/httpd_app_log.socket'); +$handler->setPersistent(true); // Now add the handler $logger->pushHandler($handler, Logger::DEBUG); @@ -34,51 +34,3 @@ In this example, using syslog-ng, you should see the log on the log server: cweb1 [2012-02-26 00:12:03] my_logger.INFO: My logger is now ready [] [] - -Symfony2 Example ----------------- - -In Symfony2, first we have to create the handler service in our services.xml (or similar): - -```xml - - - %logging.socket.connection_string% - - 2 - - - 2 - - - - - - - - - - -``` - -And then, change our config.yml (or similar): - -```yaml -parameters: - logging.socket.connection_string: 'unix:///var/log/httpd_app_log.socket' - -monolog: - handlers: - main: - type: stream - path: %kernel.logs_dir%/%kernel.environment%.log - level: debug - firephp: - type: firephp - level: info - custom: - type: service - id: logging.socket_handler -``` From 9f5681fa8175db75610d9456a164292dc7e353ed Mon Sep 17 00:00:00 2001 From: Pablo Belloc Date: Sun, 26 Feb 2012 12:03:42 -0300 Subject: [PATCH 06/13] add licensce and move @author to phpdoc --- src/Monolog/Handler/SocketHandler.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Monolog/Handler/SocketHandler.php b/src/Monolog/Handler/SocketHandler.php index 32a9295d..c4768cef 100644 --- a/src/Monolog/Handler/SocketHandler.php +++ b/src/Monolog/Handler/SocketHandler.php @@ -1,6 +1,12 @@ + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Monolog\Handler; @@ -13,6 +19,7 @@ use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; /** * Stores to any socket - uses fsockopen() or pfsockopen(). * + * @author Pablo de Leon Belloc * @see http://php.net/manual/en/function.fsockopen.php */ class SocketHandler extends AbstractProcessingHandler From cc9c02250ca3119fd8954155790d4d5872ea9434 Mon Sep 17 00:00:00 2001 From: Pablo de Leon Belloc Date: Sun, 26 Feb 2012 12:06:31 -0300 Subject: [PATCH 07/13] Fix doc/sockets.md --- doc/sockets.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/sockets.md b/doc/sockets.md index 98acfdab..b8028b52 100644 --- a/doc/sockets.md +++ b/doc/sockets.md @@ -4,11 +4,12 @@ Sockets Handler This handler allows you to write your logs to sockets using [fsockopen](http://php.net/fsockopen) or [pfsockopen](http://php.net/pfsockopen). +Persistent sockets are mainly useful in web environments where you gain some performance not closing/opening +the connections between requests. + Basic Example ------------- -This example e persistent connections: - ```php Date: Sun, 26 Feb 2012 14:17:19 -0300 Subject: [PATCH 08/13] Remove old SocketTest. Fix CS issues --- src/Monolog/Handler/SocketHandler.php | 63 +++++----- .../Exception/ConnectionException.php | 1 + .../Exception/WriteToSocketException.php | 1 + .../Handler/SocketHandler/SocketTest.php | 8 -- tests/Monolog/Handler/SocketHandlerTest.php | 112 +++++++++--------- 5 files changed, 92 insertions(+), 93 deletions(-) delete mode 100644 tests/Monolog/Handler/SocketHandler/SocketTest.php diff --git a/src/Monolog/Handler/SocketHandler.php b/src/Monolog/Handler/SocketHandler.php index c4768cef..0082ff2c 100644 --- a/src/Monolog/Handler/SocketHandler.php +++ b/src/Monolog/Handler/SocketHandler.php @@ -15,7 +15,6 @@ use Monolog\Logger; use Monolog\Handler\SocketHandler\Exception\ConnectionException; use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; - /** * Stores to any socket - uses fsockopen() or pfsockopen(). * @@ -24,12 +23,13 @@ use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; */ class SocketHandler extends AbstractProcessingHandler { + private $connectionString; private $connectionTimeout; private $resource; private $timeout = 0; private $persistent = false; - + /** * @param string $connectionString * @param integer $level The minimum logging level at which this handler will be triggered @@ -39,9 +39,9 @@ class SocketHandler extends AbstractProcessingHandler { parent::__construct($level, $bubble); $this->connectionString = $connectionString; - $this->connectionTimeout = (float)ini_get('default_socket_timeout'); + $this->connectionTimeout = (float) ini_get('default_socket_timeout'); } - + /** * Connect (if necessary) and write to the socket * @@ -54,7 +54,7 @@ class SocketHandler extends AbstractProcessingHandler $this->connectIfNotConnected(); $this->writeToSocket((string) $record['formatted']); } - + /** * We will not close a PersistentSocket instance so it can be reused in other requests. */ @@ -65,7 +65,7 @@ class SocketHandler extends AbstractProcessingHandler } $this->closeSocket(); } - + public function closeSocket() { if (is_resource($this->resource)) { @@ -73,12 +73,12 @@ class SocketHandler extends AbstractProcessingHandler $this->resource = null; } } - + public function setPersistent($boolean) { - $this->persistent = (boolean)$boolean; + $this->persistent = (boolean) $boolean; } - + /** * Set connection timeout. Only has effect before we connect. * @@ -88,9 +88,9 @@ class SocketHandler extends AbstractProcessingHandler public function setConnectionTimeout($seconds) { $this->validateTimeout($seconds); - $this->connectionTimeout = (float)$seconds; + $this->connectionTimeout = (float) $seconds; } - + /** * Set write timeout. Only has effect before we connect. * @@ -100,37 +100,39 @@ class SocketHandler extends AbstractProcessingHandler public function setTimeout($seconds) { $this->validateTimeout($seconds); - $this->timeout = (int)$seconds; + $this->timeout = (int) $seconds; } - + private function validateTimeout($value) { $ok = filter_var($value, FILTER_VALIDATE_INT, array('options' => array( - 'min_range' => 0, - ))); + 'min_range' => 0, + ))); if ($ok === false) { throw new \InvalidArgumentException("Timeout must be 0 or a positive integer (got $value)"); } } - + public function getConnectionString() { return $this->connectionString; } - + public function isPersistent() { return $this->persistent; } - - public function getConnectionTimeout() { + + public function getConnectionTimeout() + { return $this->connectionTimeout; } - - public function getTimeout() { + + public function getTimeout() + { return $this->timeout; } - + /** * Allow injecting a resource opened somewhere else. Used in tests. * @@ -153,7 +155,7 @@ class SocketHandler extends AbstractProcessingHandler } $this->connect(); } - + /** * Check to see if the socket is currently available. * @@ -164,15 +166,15 @@ class SocketHandler extends AbstractProcessingHandler public function isConnected() { return is_resource($this->resource) - && !feof($this->resource); // on TCP - other party can close connection. + && !feof($this->resource); // on TCP - other party can close connection. } - + private function connect() { $this->createSocketResource(); $this->setSocketTimeout(); } - + protected function createSocketResource() { if ($this->persistent) { @@ -185,14 +187,14 @@ class SocketHandler extends AbstractProcessingHandler } $this->resource = $resource; } - + private function setSocketTimeout() { if (!stream_set_timeout($this->resource, $this->timeout)) { throw new ConnectionException("Failed setting timeout with stream_set_timeout()"); } } - + protected function writeToSocket($data) { $length = strlen($data); @@ -212,7 +214,7 @@ class SocketHandler extends AbstractProcessingHandler throw new WriteToSocketException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); } } - + /** * Allow mock */ @@ -220,7 +222,7 @@ class SocketHandler extends AbstractProcessingHandler { return @fwrite($this->resource, $data); } - + /** * Allow mock */ @@ -228,4 +230,5 @@ class SocketHandler extends AbstractProcessingHandler { return stream_get_meta_data($this->resource); } + } diff --git a/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php b/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php index fd183687..fe04ccb1 100644 --- a/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php +++ b/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php @@ -13,4 +13,5 @@ namespace Monolog\Handler\SocketHandler\Exception; class ConnectionException extends \RuntimeException { + } \ No newline at end of file diff --git a/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php b/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php index c03c1b63..b387cf1a 100644 --- a/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php +++ b/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php @@ -13,4 +13,5 @@ namespace Monolog\Handler\SocketHandler\Exception; class WriteToSocketException extends \RuntimeException { + } \ No newline at end of file diff --git a/tests/Monolog/Handler/SocketHandler/SocketTest.php b/tests/Monolog/Handler/SocketHandler/SocketTest.php deleted file mode 100644 index a7b1d49f..00000000 --- a/tests/Monolog/Handler/SocketHandler/SocketTest.php +++ /dev/null @@ -1,8 +0,0 @@ -createHandler('garbage://here'); $this->writeRecord('data'); } - + /** * @expectedException \InvalidArgumentException */ @@ -47,14 +49,14 @@ class SocketHandlerTest extends TestCase $this->createHandler('localhost:1234'); $this->handler->setConnectionTimeout(-1); } - + public function testSetConnectionTimeout() { $this->createHandler('localhost:1234'); $this->handler->setConnectionTimeout(10); $this->assertEquals(10, $this->handler->getConnectionTimeout()); } - + /** * @expectedException \InvalidArgumentException */ @@ -63,20 +65,20 @@ class SocketHandlerTest extends TestCase $this->createHandler('localhost:1234'); $this->handler->setTimeout(-1); } - + public function testSetTimeout() { $this->createHandler('localhost:1234'); $this->handler->setTimeout(10); $this->assertEquals(10, $this->handler->getTimeout()); } - + public function testSetConnectionString() { $this->createHandler('tcp://localhost:9090'); $this->assertEquals('tcp://localhost:9090', $this->handler->getConnectionString()); } - + public function testConnectionRefuesed() { try { @@ -85,9 +87,10 @@ class SocketHandlerTest extends TestCase $this->writeRecord($string); $this->fail("Shoul not connect - are you running a server on 127.0.0.1:7894 ?"); } catch (\Monolog\Handler\SocketHandler\Exception\ConnectionException $e) { + } } - + /** * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException */ @@ -95,84 +98,84 @@ class SocketHandlerTest extends TestCase { $this->setMockHandler(array('createSocketResource')); $this->handler->expects($this->once()) - ->method('createSocketResource') - ->will($this->throwException(new ConnectionException())); + ->method('createSocketResource') + ->will($this->throwException(new ConnectionException())); $this->writeRecord('Hello world'); } - + /** * @expectedException Monolog\Handler\SocketHandler\Exception\WriteToSocketException */ public function testWriteFailsOnIfFwriteReturnsFalse() { $this->setMockHandler(array('fwrite')); - + $map = array( array('Hello world', 6), array('world', false), ); - + $this->handler->expects($this->exactly(2)) - ->method('fwrite') - ->will($this->returnValueMap($map)); - + ->method('fwrite') + ->will($this->returnValueMap($map)); + $this->injectMemoryResource(); $this->writeRecord('Hello world'); } - + /** * @expectedException Monolog\Handler\SocketHandler\Exception\WriteToSocketException */ public function testWriteFailsIfStreamTimesOut() { $this->setMockHandler(array('fwrite', 'stream_get_meta_data')); - + $map = array( array('Hello world', 6), array('world', 5), ); - + $this->handler->expects($this->exactly(1)) - ->method('fwrite') - ->will($this->returnValueMap($map)); + ->method('fwrite') + ->will($this->returnValueMap($map)); $this->handler->expects($this->exactly(1)) - ->method('stream_get_meta_data') - ->will($this->returnValue(array('timed_out' => true))); - - + ->method('stream_get_meta_data') + ->will($this->returnValue(array('timed_out' => true))); + + $this->injectMemoryResource(); $this->writeRecord('Hello world'); } - + /** * @expectedException Monolog\Handler\SocketHandler\Exception\WriteToSocketException */ public function testWriteFailsOnIncompleteWrite() { $this->setMockHandler(array('fwrite', 'isConnected')); - + $map = array( array('Hello world', 6), array('world', 5), ); - + $this->handler->expects($this->exactly(1)) - ->method('fwrite') - ->will($this->returnValueMap($map)); + ->method('fwrite') + ->will($this->returnValueMap($map)); $this->handler->expects($this->at(0)) - ->method('isConnected') - ->will($this->returnValue(true)); + ->method('isConnected') + ->will($this->returnValue(true)); $this->handler->expects($this->at(1)) - ->method('isConnected') - ->will($this->returnValue(true)); + ->method('isConnected') + ->will($this->returnValue(true)); $this->handler->expects($this->at(2)) - ->method('isConnected') - ->will($this->returnValue(false)); - + ->method('isConnected') + ->will($this->returnValue(false)); + $this->injectMemoryResource(); $this->writeRecord('Hello world'); } - + public function testWriteWithMemoryFile() { $this->createHandler('localhost:54321'); @@ -183,24 +186,24 @@ class SocketHandlerTest extends TestCase fseek($this->res, 0); $this->assertEquals('test1test2test3', fread($this->res, 1024)); } - + public function testWriteWithMock() { $this->setMockHandler(array('fwrite')); - + $map = array( array('Hello world', 6), array('world', 5), ); - + $this->handler->expects($this->exactly(2)) - ->method('fwrite') - ->will($this->returnValueMap($map)); - + ->method('fwrite') + ->will($this->returnValueMap($map)); + $this->injectMemoryResource(); $this->writeRecord('Hello world'); } - + public function testClose() { $this->createHandler('localhost:54321'); @@ -210,7 +213,7 @@ class SocketHandlerTest extends TestCase $this->handler->close(); $this->assertFalse(is_resource($this->res)); } - + public function testCloseDoesNotClosePersistentSocket() { $this->createHandler('localhost:54321'); @@ -230,31 +233,30 @@ class SocketHandlerTest extends TestCase $this->createHandler(''); $this->handler->setResource(''); } - + private function createHandler($connectionString) { $this->handler = new SocketHandler($connectionString); $this->handler->setFormatter($this->getIdentityFormatter()); } - + private function writeRecord($string) { $this->handler->handle($this->getRecord(Logger::WARNING, $string)); } - + private function injectMemoryResource() { $this->res = fopen('php://memory', 'a'); $this->handler->setResource($this->res); } - + private function setMockHandler(array $methods) { $this->handler = $this->getMock( - '\Monolog\Handler\SocketHandler', - $methods, - array('localhost:1234') + '\Monolog\Handler\SocketHandler', $methods, array('localhost:1234') ); $this->handler->setFormatter($this->getIdentityFormatter()); } + } From 83e1e2d80a4933e5019d396b9466fec5690fb393 Mon Sep 17 00:00:00 2001 From: Pablo de Leon Belloc Date: Mon, 27 Feb 2012 12:38:06 -0300 Subject: [PATCH 09/13] Improve tests on SocketHandler --- src/Monolog/Handler/SocketHandler.php | 57 ++++++---- tests/Monolog/Handler/SocketHandlerTest.php | 114 ++++++++++++-------- 2 files changed, 103 insertions(+), 68 deletions(-) diff --git a/src/Monolog/Handler/SocketHandler.php b/src/Monolog/Handler/SocketHandler.php index 0082ff2c..ec11864c 100644 --- a/src/Monolog/Handler/SocketHandler.php +++ b/src/Monolog/Handler/SocketHandler.php @@ -29,6 +29,8 @@ class SocketHandler extends AbstractProcessingHandler private $resource; private $timeout = 0; private $persistent = false; + private $errno; + private $errstr; /** * @param string $connectionString @@ -133,21 +135,6 @@ class SocketHandler extends AbstractProcessingHandler return $this->timeout; } - /** - * Allow injecting a resource opened somewhere else. Used in tests. - * - * @throws \InvalidArgumentException - * @param resource $resource - */ - public function setResource($resource) - { - if (is_resource($resource)) { - $this->resource = $resource; - } else { - throw new \InvalidArgumentException("Expected a resource"); - } - } - private function connectIfNotConnected() { if ($this->isConnected()) { @@ -175,27 +162,27 @@ class SocketHandler extends AbstractProcessingHandler $this->setSocketTimeout(); } - protected function createSocketResource() + private function createSocketResource() { - if ($this->persistent) { - @$resource = pfsockopen($this->connectionString, -1, $errno, $errstr, $this->connectionTimeout); + if ($this->isPersistent()) { + $resource = $this->pfsockopen(); } else { - @$resource = fsockopen($this->connectionString, -1, $errno, $errstr, $this->connectionTimeout); + $resource = $this->fsockopen(); } if (!$resource) { - throw new ConnectionException("Failed connecting to $this->connectionString ($errno: $errstr)"); + throw new ConnectionException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)"); } - $this->resource = $resource; + return $this->resource = $resource; } private function setSocketTimeout() { - if (!stream_set_timeout($this->resource, $this->timeout)) { + if (!$this->stream_set_timeout()) { throw new ConnectionException("Failed setting timeout with stream_set_timeout()"); } } - protected function writeToSocket($data) + private function writeToSocket($data) { $length = strlen($data); $sent = 0; @@ -215,6 +202,30 @@ class SocketHandler extends AbstractProcessingHandler } } + /** + * Allow mock + */ + protected function pfsockopen() + { + return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); + } + + /** + * Allow mock + */ + protected function fsockopen() + { + return @fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); + } + + /** + * Allow mock + */ + protected function stream_set_timeout() + { + return stream_set_timeout($this->resource, $this->timeout); + } + /** * Allow mock */ diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php index 5e33dbd8..51bc09e8 100644 --- a/tests/Monolog/Handler/SocketHandlerTest.php +++ b/tests/Monolog/Handler/SocketHandlerTest.php @@ -94,12 +94,37 @@ class SocketHandlerTest extends TestCase /** * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException */ - public function testConnectionTimeoutWithMock() + public function testExceptionIsThrownOnFsockopenError() { - $this->setMockHandler(array('createSocketResource')); + $this->setMockHandler(array('fsockopen')); $this->handler->expects($this->once()) - ->method('createSocketResource') - ->will($this->throwException(new ConnectionException())); + ->method('fsockopen') + ->will($this->returnValue(false)); + $this->writeRecord('Hello world'); + } + + /** + * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException + */ + public function testExceptionIsThrownOnPfsockopenError() + { + $this->setMockHandler(array('pfsockopen')); + $this->handler->expects($this->once()) + ->method('pfsockopen') + ->will($this->returnValue(false)); + $this->handler->setPersistent(true); + $this->writeRecord('Hello world'); + } + + /** + * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException + */ + public function testExceptionIsThrownIfCannotSetTimeout() + { + $this->setMockHandler(array('stream_set_timeout')); + $this->handler->expects($this->once()) + ->method('stream_set_timeout') + ->will($this->returnValue(false)); $this->writeRecord('Hello world'); } @@ -119,7 +144,6 @@ class SocketHandlerTest extends TestCase ->method('fwrite') ->will($this->returnValueMap($map)); - $this->injectMemoryResource(); $this->writeRecord('Hello world'); } @@ -143,7 +167,6 @@ class SocketHandlerTest extends TestCase ->will($this->returnValue(array('timed_out' => true))); - $this->injectMemoryResource(); $this->writeRecord('Hello world'); } @@ -152,34 +175,27 @@ class SocketHandlerTest extends TestCase */ public function testWriteFailsOnIncompleteWrite() { - $this->setMockHandler(array('fwrite', 'isConnected')); + $this->setMockHandler(array('fwrite', 'stream_get_meta_data')); - $map = array( - array('Hello world', 6), - array('world', 5), - ); + $res = $this->res; + $callback = function($string) use ($res) { + fclose($res); + return strlen('Hello'); + }; $this->handler->expects($this->exactly(1)) ->method('fwrite') - ->will($this->returnValueMap($map)); - $this->handler->expects($this->at(0)) - ->method('isConnected') - ->will($this->returnValue(true)); - $this->handler->expects($this->at(1)) - ->method('isConnected') - ->will($this->returnValue(true)); - $this->handler->expects($this->at(2)) - ->method('isConnected') - ->will($this->returnValue(false)); + ->will($this->returnCallback($callback)); + $this->handler->expects($this->exactly(1)) + ->method('stream_get_meta_data') + ->will($this->returnValue(array('timed_out' => false))); - $this->injectMemoryResource(); $this->writeRecord('Hello world'); } public function testWriteWithMemoryFile() { - $this->createHandler('localhost:54321'); - $this->injectMemoryResource(); + $this->setMockHandler(); $this->writeRecord('test1'); $this->writeRecord('test2'); $this->writeRecord('test3'); @@ -200,14 +216,12 @@ class SocketHandlerTest extends TestCase ->method('fwrite') ->will($this->returnValueMap($map)); - $this->injectMemoryResource(); $this->writeRecord('Hello world'); } public function testClose() { - $this->createHandler('localhost:54321'); - $this->injectMemoryResource(); + $this->setMockHandler(); $this->writeRecord('Hello world'); $this->assertTrue(is_resource($this->res)); $this->handler->close(); @@ -216,24 +230,14 @@ class SocketHandlerTest extends TestCase public function testCloseDoesNotClosePersistentSocket() { - $this->createHandler('localhost:54321'); + $this->setMockHandler(); $this->handler->setPersistent(true); - $this->injectMemoryResource(); $this->writeRecord('Hello world'); $this->assertTrue(is_resource($this->res)); $this->handler->close(); $this->assertTrue(is_resource($this->res)); } - /** - * @expectedException \InvalidArgumentException - */ - public function testInjectBadResourceThrowsException() - { - $this->createHandler(''); - $this->handler->setResource(''); - } - private function createHandler($connectionString) { $this->handler = new SocketHandler($connectionString); @@ -245,18 +249,38 @@ class SocketHandlerTest extends TestCase $this->handler->handle($this->getRecord(Logger::WARNING, $string)); } - private function injectMemoryResource() + private function setMockHandler(array $methods = array()) { $this->res = fopen('php://memory', 'a'); - $this->handler->setResource($this->res); - } - private function setMockHandler(array $methods) - { + $defaultMethods = array('fsockopen', 'pfsockopen', 'stream_set_timeout'); + $newMethods = array_diff($methods, $defaultMethods); + + $finalMethods = array_merge($defaultMethods, $newMethods); + $this->handler = $this->getMock( - '\Monolog\Handler\SocketHandler', $methods, array('localhost:1234') + '\Monolog\Handler\SocketHandler', $finalMethods, array('localhost:1234') ); + + if (!in_array('fsockopen', $methods)) { + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + } + + if (!in_array('pfsockopen', $methods)) { + $this->handler->expects($this->any()) + ->method('pfsockopen') + ->will($this->returnValue($this->res)); + } + + if (!in_array('stream_set_timeout', $methods)) { + $this->handler->expects($this->any()) + ->method('stream_set_timeout') + ->will($this->returnValue(true)); + } + $this->handler->setFormatter($this->getIdentityFormatter()); } - + } From bee3e1bca4c1a9ed45e3b0671a2327bdc4720380 Mon Sep 17 00:00:00 2001 From: Pablo Belloc Date: Wed, 28 Mar 2012 08:49:25 -0300 Subject: [PATCH 10/13] Remove SocketHandler's ConnecitonException and WriteToSocketException - replace them with \UnexpectedValueException and \RuntimeException respectively --- src/Monolog/Handler/SocketHandler.php | 16 +++++++--------- .../Exception/ConnectionException.php | 17 ----------------- .../Exception/WriteToSocketException.php | 17 ----------------- tests/Monolog/Handler/SocketHandlerTest.php | 18 ++++++++---------- 4 files changed, 15 insertions(+), 53 deletions(-) delete mode 100644 src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php delete mode 100644 src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php diff --git a/src/Monolog/Handler/SocketHandler.php b/src/Monolog/Handler/SocketHandler.php index ec11864c..ee93b0f2 100644 --- a/src/Monolog/Handler/SocketHandler.php +++ b/src/Monolog/Handler/SocketHandler.php @@ -12,8 +12,6 @@ namespace Monolog\Handler; use Monolog\Logger; -use Monolog\Handler\SocketHandler\Exception\ConnectionException; -use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; /** * Stores to any socket - uses fsockopen() or pfsockopen(). @@ -47,8 +45,8 @@ class SocketHandler extends AbstractProcessingHandler /** * Connect (if necessary) and write to the socket * - * @throws Monolog\Handler\SocketHandler\Exception\ConnectionException - * @throws Monolog\Handler\SocketHandler\Exception\WriteToSocketException + * @throws \UnexpectedValueException + * @throws \RuntimeException * @param string $string */ public function write(array $record) @@ -170,7 +168,7 @@ class SocketHandler extends AbstractProcessingHandler $resource = $this->fsockopen(); } if (!$resource) { - throw new ConnectionException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)"); + throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)"); } return $this->resource = $resource; } @@ -178,7 +176,7 @@ class SocketHandler extends AbstractProcessingHandler private function setSocketTimeout() { if (!$this->stream_set_timeout()) { - throw new ConnectionException("Failed setting timeout with stream_set_timeout()"); + throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()"); } } @@ -189,16 +187,16 @@ class SocketHandler extends AbstractProcessingHandler while ($this->isConnected() && $sent < $length) { $chunk = $this->fwrite(substr($data, $sent)); if ($chunk === false) { - throw new WriteToSocketException("Could not write to socket"); + throw new \RuntimeException("Could not write to socket"); } $sent += $chunk; $socketInfo = $this->stream_get_meta_data(); if ($socketInfo['timed_out']) { - throw new WriteToSocketException("Write timed-out"); + throw new \RuntimeException("Write timed-out"); } } if (!$this->isConnected() && $sent < $length) { - throw new WriteToSocketException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); + throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); } } diff --git a/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php b/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php deleted file mode 100644 index fe04ccb1..00000000 --- a/src/Monolog/Handler/SocketHandler/Exception/ConnectionException.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Monolog\Handler\SocketHandler\Exception; - -class ConnectionException extends \RuntimeException -{ - -} \ No newline at end of file diff --git a/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php b/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php deleted file mode 100644 index b387cf1a..00000000 --- a/src/Monolog/Handler/SocketHandler/Exception/WriteToSocketException.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Monolog\Handler\SocketHandler\Exception; - -class WriteToSocketException extends \RuntimeException -{ - -} \ No newline at end of file diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php index 51bc09e8..b2f4d224 100644 --- a/tests/Monolog/Handler/SocketHandlerTest.php +++ b/tests/Monolog/Handler/SocketHandlerTest.php @@ -13,8 +13,6 @@ namespace Monolog\Handler; use Monolog\TestCase; use Monolog\Logger; -use Monolog\Handler\SocketHandler\Exception\ConnectionException; -use Monolog\Handler\SocketHandler\Exception\WriteToSocketException; /** * @author Pablo de Leon Belloc @@ -33,7 +31,7 @@ class SocketHandlerTest extends TestCase private $res; /** - * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException + * @expectedException UnexpectedValueException */ public function testInvalidHostname() { @@ -86,13 +84,13 @@ class SocketHandlerTest extends TestCase $string = 'Hello world'; $this->writeRecord($string); $this->fail("Shoul not connect - are you running a server on 127.0.0.1:7894 ?"); - } catch (\Monolog\Handler\SocketHandler\Exception\ConnectionException $e) { + } catch (\UnexpectedValueException $e) { } } /** - * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException + * @expectedException UnexpectedValueException */ public function testExceptionIsThrownOnFsockopenError() { @@ -104,7 +102,7 @@ class SocketHandlerTest extends TestCase } /** - * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException + * @expectedException UnexpectedValueException */ public function testExceptionIsThrownOnPfsockopenError() { @@ -117,7 +115,7 @@ class SocketHandlerTest extends TestCase } /** - * @expectedException Monolog\Handler\SocketHandler\Exception\ConnectionException + * @expectedException UnexpectedValueException */ public function testExceptionIsThrownIfCannotSetTimeout() { @@ -129,7 +127,7 @@ class SocketHandlerTest extends TestCase } /** - * @expectedException Monolog\Handler\SocketHandler\Exception\WriteToSocketException + * @expectedException RuntimeException */ public function testWriteFailsOnIfFwriteReturnsFalse() { @@ -148,7 +146,7 @@ class SocketHandlerTest extends TestCase } /** - * @expectedException Monolog\Handler\SocketHandler\Exception\WriteToSocketException + * @expectedException RuntimeException */ public function testWriteFailsIfStreamTimesOut() { @@ -171,7 +169,7 @@ class SocketHandlerTest extends TestCase } /** - * @expectedException Monolog\Handler\SocketHandler\Exception\WriteToSocketException + * @expectedException RuntimeException */ public function testWriteFailsOnIncompleteWrite() { From 84f4a44850ba89140ba67ddfcae7e05baac1f34f Mon Sep 17 00:00:00 2001 From: Pablo Belloc Date: Wed, 28 Mar 2012 09:28:00 -0300 Subject: [PATCH 11/13] Make SocketHandlerTest PHPUnit 3.5+ compatible --- tests/Monolog/Handler/SocketHandlerTest.php | 45 ++++++++++++--------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php index b2f4d224..fde22cd5 100644 --- a/tests/Monolog/Handler/SocketHandlerTest.php +++ b/tests/Monolog/Handler/SocketHandlerTest.php @@ -132,15 +132,18 @@ class SocketHandlerTest extends TestCase public function testWriteFailsOnIfFwriteReturnsFalse() { $this->setMockHandler(array('fwrite')); - - $map = array( - array('Hello world', 6), - array('world', false), - ); + + $callback = function($arg) { + $map = array( + 'Hello world' => 6, + 'world' => false, + ); + return $map[$arg]; + }; $this->handler->expects($this->exactly(2)) ->method('fwrite') - ->will($this->returnValueMap($map)); + ->will($this->returnCallback($callback)); $this->writeRecord('Hello world'); } @@ -151,15 +154,18 @@ class SocketHandlerTest extends TestCase public function testWriteFailsIfStreamTimesOut() { $this->setMockHandler(array('fwrite', 'stream_get_meta_data')); - - $map = array( - array('Hello world', 6), - array('world', 5), - ); + + $callback = function($arg) { + $map = array( + 'Hello world' => 6, + 'world' => 5, + ); + return $map[$arg]; + }; $this->handler->expects($this->exactly(1)) ->method('fwrite') - ->will($this->returnValueMap($map)); + ->will($this->returnCallback($callback)); $this->handler->expects($this->exactly(1)) ->method('stream_get_meta_data') ->will($this->returnValue(array('timed_out' => true))); @@ -204,15 +210,18 @@ class SocketHandlerTest extends TestCase public function testWriteWithMock() { $this->setMockHandler(array('fwrite')); - - $map = array( - array('Hello world', 6), - array('world', 5), - ); + + $callback = function($arg) { + $map = array( + 'Hello world' => 6, + 'world' => 5, + ); + return $map[$arg]; + }; $this->handler->expects($this->exactly(2)) ->method('fwrite') - ->will($this->returnValueMap($map)); + ->will($this->returnCallback($callback)); $this->writeRecord('Hello world'); } From a35db5bcdba55440c9b172d307372b200bb7c308 Mon Sep 17 00:00:00 2001 From: Pablo de Leon Belloc Date: Sun, 1 Apr 2012 20:43:39 -0300 Subject: [PATCH 12/13] SocketHandler: Coding standard fixes. Remove redundant test. --- src/Monolog/Handler/SocketHandler.php | 177 ++++++++++++-------- tests/Monolog/Handler/SocketHandlerTest.php | 116 ++++++------- 2 files changed, 156 insertions(+), 137 deletions(-) diff --git a/src/Monolog/Handler/SocketHandler.php b/src/Monolog/Handler/SocketHandler.php index ee93b0f2..bcb7466a 100644 --- a/src/Monolog/Handler/SocketHandler.php +++ b/src/Monolog/Handler/SocketHandler.php @@ -17,7 +17,7 @@ use Monolog\Logger; * Stores to any socket - uses fsockopen() or pfsockopen(). * * @author Pablo de Leon Belloc - * @see http://php.net/manual/en/function.fsockopen.php + * @see http://php.net/manual/en/function.fsockopen.php */ class SocketHandler extends AbstractProcessingHandler { @@ -31,9 +31,9 @@ class SocketHandler extends AbstractProcessingHandler private $errstr; /** - * @param string $connectionString - * @param integer $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param string $connectionString Socket connection string + * @param integer $level The minimum logging level at which this handler will be triggered + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true) { @@ -45,9 +45,10 @@ class SocketHandler extends AbstractProcessingHandler /** * Connect (if necessary) and write to the socket * + * @param array $record + * * @throws \UnexpectedValueException * @throws \RuntimeException - * @param string $string */ public function write(array $record) { @@ -66,6 +67,9 @@ class SocketHandler extends AbstractProcessingHandler $this->closeSocket(); } + /** + * Close socket, if open + */ public function closeSocket() { if (is_resource($this->resource)) { @@ -74,6 +78,11 @@ class SocketHandler extends AbstractProcessingHandler } } + /** + * Set socket connection to nbe persistent. It only has effect before the connection is initiated. + * + * @param type $boolean + */ public function setPersistent($boolean) { $this->persistent = (boolean) $boolean; @@ -82,8 +91,9 @@ class SocketHandler extends AbstractProcessingHandler /** * Set connection timeout. Only has effect before we connect. * - * @see http://php.net/manual/en/function.fsockopen.php * @param integer $seconds + * + * @see http://php.net/manual/en/function.fsockopen.php */ public function setConnectionTimeout($seconds) { @@ -94,8 +104,9 @@ class SocketHandler extends AbstractProcessingHandler /** * Set write timeout. Only has effect before we connect. * - * @see http://php.net/manual/en/function.stream-set-timeout.php * @param type $seconds + * + * @see http://php.net/manual/en/function.stream-set-timeout.php */ public function setTimeout($seconds) { @@ -103,44 +114,46 @@ class SocketHandler extends AbstractProcessingHandler $this->timeout = (int) $seconds; } - private function validateTimeout($value) - { - $ok = filter_var($value, FILTER_VALIDATE_INT, array('options' => array( - 'min_range' => 0, - ))); - if ($ok === false) { - throw new \InvalidArgumentException("Timeout must be 0 or a positive integer (got $value)"); - } - } - + /** + * Get current connection string + * + * @return string + */ public function getConnectionString() { return $this->connectionString; } + /** + * Get persistent setting + * + * @return boolean + */ public function isPersistent() { return $this->persistent; } + /** + * Get current connection timeout setting + * + * @return float + */ public function getConnectionTimeout() { return $this->connectionTimeout; } + /** + * Get current in-transfer timeout + * + * @return float + */ public function getTimeout() { return $this->timeout; } - private function connectIfNotConnected() - { - if ($this->isConnected()) { - return; - } - $this->connect(); - } - /** * Check to see if the socket is currently available. * @@ -151,55 +164,9 @@ class SocketHandler extends AbstractProcessingHandler public function isConnected() { return is_resource($this->resource) - && !feof($this->resource); // on TCP - other party can close connection. + && !feof($this->resource); // on TCP - other party can close connection. } - - private function connect() - { - $this->createSocketResource(); - $this->setSocketTimeout(); - } - - private function createSocketResource() - { - if ($this->isPersistent()) { - $resource = $this->pfsockopen(); - } else { - $resource = $this->fsockopen(); - } - if (!$resource) { - throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)"); - } - return $this->resource = $resource; - } - - private function setSocketTimeout() - { - if (!$this->stream_set_timeout()) { - throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()"); - } - } - - private function writeToSocket($data) - { - $length = strlen($data); - $sent = 0; - while ($this->isConnected() && $sent < $length) { - $chunk = $this->fwrite(substr($data, $sent)); - if ($chunk === false) { - throw new \RuntimeException("Could not write to socket"); - } - $sent += $chunk; - $socketInfo = $this->stream_get_meta_data(); - if ($socketInfo['timed_out']) { - throw new \RuntimeException("Write timed-out"); - } - } - if (!$this->isConnected() && $sent < $length) { - throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); - } - } - + /** * Allow mock */ @@ -240,4 +207,68 @@ class SocketHandler extends AbstractProcessingHandler return stream_get_meta_data($this->resource); } + private function validateTimeout($value) + { + $ok = filter_var($value, FILTER_VALIDATE_INT, array('options' => array( + 'min_range' => 0, + ))); + if ($ok === false) { + throw new \InvalidArgumentException("Timeout must be 0 or a positive integer (got $value)"); + } + } + + private function connectIfNotConnected() + { + if ($this->isConnected()) { + return; + } + $this->connect(); + } + + private function connect() + { + $this->createSocketResource(); + $this->setSocketTimeout(); + } + + private function createSocketResource() + { + if ($this->isPersistent()) { + $resource = $this->pfsockopen(); + } else { + $resource = $this->fsockopen(); + } + if (!$resource) { + throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)"); + } + $this->resource = $resource; + } + + private function setSocketTimeout() + { + if (!$this->stream_set_timeout()) { + throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()"); + } + } + + private function writeToSocket($data) + { + $length = strlen($data); + $sent = 0; + while ($this->isConnected() && $sent < $length) { + $chunk = $this->fwrite(substr($data, $sent)); + if ($chunk === false) { + throw new \RuntimeException("Could not write to socket"); + } + $sent += $chunk; + $socketInfo = $this->stream_get_meta_data(); + if ($socketInfo['timed_out']) { + throw new \RuntimeException("Write timed-out"); + } + } + if (!$this->isConnected() && $sent < $length) { + throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); + } + } + } diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php index fde22cd5..ba969c29 100644 --- a/tests/Monolog/Handler/SocketHandlerTest.php +++ b/tests/Monolog/Handler/SocketHandlerTest.php @@ -77,18 +77,6 @@ class SocketHandlerTest extends TestCase $this->assertEquals('tcp://localhost:9090', $this->handler->getConnectionString()); } - public function testConnectionRefuesed() - { - try { - $this->createHandler('127.0.0.1:7894'); - $string = 'Hello world'; - $this->writeRecord($string); - $this->fail("Shoul not connect - are you running a server on 127.0.0.1:7894 ?"); - } catch (\UnexpectedValueException $e) { - - } - } - /** * @expectedException UnexpectedValueException */ @@ -96,8 +84,8 @@ class SocketHandlerTest extends TestCase { $this->setMockHandler(array('fsockopen')); $this->handler->expects($this->once()) - ->method('fsockopen') - ->will($this->returnValue(false)); + ->method('fsockopen') + ->will($this->returnValue(false)); $this->writeRecord('Hello world'); } @@ -108,8 +96,8 @@ class SocketHandlerTest extends TestCase { $this->setMockHandler(array('pfsockopen')); $this->handler->expects($this->once()) - ->method('pfsockopen') - ->will($this->returnValue(false)); + ->method('pfsockopen') + ->will($this->returnValue(false)); $this->handler->setPersistent(true); $this->writeRecord('Hello world'); } @@ -121,8 +109,8 @@ class SocketHandlerTest extends TestCase { $this->setMockHandler(array('stream_set_timeout')); $this->handler->expects($this->once()) - ->method('stream_set_timeout') - ->will($this->returnValue(false)); + ->method('stream_set_timeout') + ->will($this->returnValue(false)); $this->writeRecord('Hello world'); } @@ -132,18 +120,18 @@ class SocketHandlerTest extends TestCase public function testWriteFailsOnIfFwriteReturnsFalse() { $this->setMockHandler(array('fwrite')); - + $callback = function($arg) { - $map = array( - 'Hello world' => 6, - 'world' => false, - ); - return $map[$arg]; - }; + $map = array( + 'Hello world' => 6, + 'world' => false, + ); + return $map[$arg]; + }; $this->handler->expects($this->exactly(2)) - ->method('fwrite') - ->will($this->returnCallback($callback)); + ->method('fwrite') + ->will($this->returnCallback($callback)); $this->writeRecord('Hello world'); } @@ -154,21 +142,21 @@ class SocketHandlerTest extends TestCase public function testWriteFailsIfStreamTimesOut() { $this->setMockHandler(array('fwrite', 'stream_get_meta_data')); - + $callback = function($arg) { - $map = array( - 'Hello world' => 6, - 'world' => 5, - ); - return $map[$arg]; - }; + $map = array( + 'Hello world' => 6, + 'world' => 5, + ); + return $map[$arg]; + }; $this->handler->expects($this->exactly(1)) - ->method('fwrite') - ->will($this->returnCallback($callback)); + ->method('fwrite') + ->will($this->returnCallback($callback)); $this->handler->expects($this->exactly(1)) - ->method('stream_get_meta_data') - ->will($this->returnValue(array('timed_out' => true))); + ->method('stream_get_meta_data') + ->will($this->returnValue(array('timed_out' => true))); $this->writeRecord('Hello world'); @@ -183,16 +171,16 @@ class SocketHandlerTest extends TestCase $res = $this->res; $callback = function($string) use ($res) { - fclose($res); - return strlen('Hello'); - }; + fclose($res); + return strlen('Hello'); + }; $this->handler->expects($this->exactly(1)) - ->method('fwrite') - ->will($this->returnCallback($callback)); + ->method('fwrite') + ->will($this->returnCallback($callback)); $this->handler->expects($this->exactly(1)) - ->method('stream_get_meta_data') - ->will($this->returnValue(array('timed_out' => false))); + ->method('stream_get_meta_data') + ->will($this->returnValue(array('timed_out' => false))); $this->writeRecord('Hello world'); } @@ -210,18 +198,18 @@ class SocketHandlerTest extends TestCase public function testWriteWithMock() { $this->setMockHandler(array('fwrite')); - + $callback = function($arg) { - $map = array( - 'Hello world' => 6, - 'world' => 5, - ); - return $map[$arg]; - }; + $map = array( + 'Hello world' => 6, + 'world' => 5, + ); + return $map[$arg]; + }; $this->handler->expects($this->exactly(2)) - ->method('fwrite') - ->will($this->returnCallback($callback)); + ->method('fwrite') + ->will($this->returnCallback($callback)); $this->writeRecord('Hello world'); } @@ -230,9 +218,9 @@ class SocketHandlerTest extends TestCase { $this->setMockHandler(); $this->writeRecord('Hello world'); - $this->assertTrue(is_resource($this->res)); + $this->assertInternalType('resource', $this->res); $this->handler->close(); - $this->assertFalse(is_resource($this->res)); + $this->assertFalse(is_resource($this->res), "Expected resource to be closed after closing handler"); } public function testCloseDoesNotClosePersistentSocket() @@ -266,28 +254,28 @@ class SocketHandlerTest extends TestCase $finalMethods = array_merge($defaultMethods, $newMethods); $this->handler = $this->getMock( - '\Monolog\Handler\SocketHandler', $finalMethods, array('localhost:1234') + '\Monolog\Handler\SocketHandler', $finalMethods, array('localhost:1234') ); if (!in_array('fsockopen', $methods)) { $this->handler->expects($this->any()) - ->method('fsockopen') - ->will($this->returnValue($this->res)); + ->method('fsockopen') + ->will($this->returnValue($this->res)); } if (!in_array('pfsockopen', $methods)) { $this->handler->expects($this->any()) - ->method('pfsockopen') - ->will($this->returnValue($this->res)); + ->method('pfsockopen') + ->will($this->returnValue($this->res)); } if (!in_array('stream_set_timeout', $methods)) { $this->handler->expects($this->any()) - ->method('stream_set_timeout') - ->will($this->returnValue(true)); + ->method('stream_set_timeout') + ->will($this->returnValue(true)); } $this->handler->setFormatter($this->getIdentityFormatter()); } - + } From 8826a940418963d2051d352c90069cdbbbffbfbe Mon Sep 17 00:00:00 2001 From: Pablo de Leon Belloc Date: Sun, 1 Apr 2012 21:11:25 -0300 Subject: [PATCH 13/13] Yet another CS fix on SocketHandlerTest --- tests/Monolog/Handler/SocketHandlerTest.php | 54 +++++++++++---------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php index ba969c29..eada7373 100644 --- a/tests/Monolog/Handler/SocketHandlerTest.php +++ b/tests/Monolog/Handler/SocketHandlerTest.php @@ -121,13 +121,14 @@ class SocketHandlerTest extends TestCase { $this->setMockHandler(array('fwrite')); - $callback = function($arg) { - $map = array( - 'Hello world' => 6, - 'world' => false, - ); - return $map[$arg]; - }; + $callback = function($arg) + { + $map = array( + 'Hello world' => 6, + 'world' => false, + ); + return $map[$arg]; + }; $this->handler->expects($this->exactly(2)) ->method('fwrite') @@ -143,13 +144,14 @@ class SocketHandlerTest extends TestCase { $this->setMockHandler(array('fwrite', 'stream_get_meta_data')); - $callback = function($arg) { - $map = array( - 'Hello world' => 6, - 'world' => 5, - ); - return $map[$arg]; - }; + $callback = function($arg) + { + $map = array( + 'Hello world' => 6, + 'world' => 5, + ); + return $map[$arg]; + }; $this->handler->expects($this->exactly(1)) ->method('fwrite') @@ -170,10 +172,11 @@ class SocketHandlerTest extends TestCase $this->setMockHandler(array('fwrite', 'stream_get_meta_data')); $res = $this->res; - $callback = function($string) use ($res) { - fclose($res); - return strlen('Hello'); - }; + $callback = function($string) use ($res) + { + fclose($res); + return strlen('Hello'); + }; $this->handler->expects($this->exactly(1)) ->method('fwrite') @@ -199,13 +202,14 @@ class SocketHandlerTest extends TestCase { $this->setMockHandler(array('fwrite')); - $callback = function($arg) { - $map = array( - 'Hello world' => 6, - 'world' => 5, - ); - return $map[$arg]; - }; + $callback = function($arg) + { + $map = array( + 'Hello world' => 6, + 'world' => 5, + ); + return $map[$arg]; + }; $this->handler->expects($this->exactly(2)) ->method('fwrite')