Source of file SocketHandler.php
Size: 7,332 Bytes - Last Modified: 2013-04-23T12:09:48+02:00
/home/theseer/Downloads/Symfony/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 | <?php /* * This file is part of the Monolog package. * * (c) Jordi Boggiano <j.boggiano@seld.be> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Stores to any socket - uses fsockopen() or pfsockopen(). * * @author Pablo de Leon Belloc <pablolb@gmail.com> * @see http://php.net/manual/en/function.fsockopen.php */ class SocketHandler extends AbstractProcessingHandler { private $connectionString; private $connectionTimeout; private $resource; private $timeout = 0; private $persistent = false; private $errno; private $errstr; /** * @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) { parent::__construct($level, $bubble); $this->connectionString = $connectionString; $this->connectionTimeout = (float) ini_get('default_socket_timeout'); } /** * Connect (if necessary) and write to the socket * * @param array $record * * @throws \UnexpectedValueException * @throws \RuntimeException */ public function write(array $record) { $this->connectIfNotConnected(); $data = $this->generateDataStream($record); $this->writeToSocket($data); } /** * We will not close a PersistentSocket instance so it can be reused in other requests. */ public function close() { if (!$this->isPersistent()) { $this->closeSocket(); } } /** * Close socket, if open */ public function closeSocket() { if (is_resource($this->resource)) { fclose($this->resource); $this->resource = null; } } /** * 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; } /** * Set connection timeout. Only has effect before we connect. * * @param float $seconds * * @see http://php.net/manual/en/function.fsockopen.php */ public function setConnectionTimeout($seconds) { $this->validateTimeout($seconds); $this->connectionTimeout = (float) $seconds; } /** * Set write timeout. Only has effect before we connect. * * @param float $seconds * * @see http://php.net/manual/en/function.stream-set-timeout.php */ public function setTimeout($seconds) { $this->validateTimeout($seconds); $this->timeout = (float) $seconds; } /** * 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; } /** * 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. } /** * Wrapper to allow mocking */ protected function pfsockopen() { return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); } /** * Wrapper to allow mocking */ protected function fsockopen() { return @fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); } /** * Wrapper to allow mocking * * @see http://php.net/manual/en/function.stream-set-timeout.php */ protected function streamSetTimeout() { $seconds = floor($this->timeout); $microseconds = round(($this->timeout - $seconds)*1e6); return stream_set_timeout($this->resource, $seconds, $microseconds); } /** * Wrapper to allow mocking */ protected function fwrite($data) { return @fwrite($this->resource, $data); } /** * Wrapper to allow mocking */ protected function streamGetMetadata() { return stream_get_meta_data($this->resource); } private function validateTimeout($value) { $ok = filter_var($value, FILTER_VALIDATE_FLOAT); if ($ok === false || $value < 0) { throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got $value)"); } } private function connectIfNotConnected() { if ($this->isConnected()) { return; } $this->connect(); } protected function generateDataStream($record) { return (string) $record['formatted']; } 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->streamSetTimeout()) { throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()"); } } private function writeToSocket($data) { $length = strlen($data); $sent = 0; while ($this->isConnected() && $sent < $length) { if (0 == $sent) { $chunk = $this->fwrite($data); } else { $chunk = $this->fwrite(substr($data, $sent)); } if ($chunk === false) { throw new \RuntimeException("Could not write to socket"); } $sent += $chunk; $socketInfo = $this->streamGetMetadata(); 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)"); } } } |