#4694 add feedback during installation, monolog
parent
687324f601
commit
7a0b55cbcf
@ -0,0 +1,149 @@ |
||||
<?php |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Description of log |
||||
* |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class Log |
||||
{ |
||||
|
||||
private static function register_autoload() |
||||
{ |
||||
static $has_run = false; |
||||
if ($has_run) { |
||||
return true; |
||||
} |
||||
|
||||
$directory = api_get_path(LIBRARY_PATH) . 'symfony'; |
||||
if (!class_exists('Doctrine\Common\ClassLoader', false)) { |
||||
require_once $directory . '/doctrine/Common/ClassLoader.php'; |
||||
} |
||||
|
||||
$loader = new Doctrine\Common\ClassLoader('Monolog', $directory); |
||||
$loader->register(); |
||||
|
||||
$has_run = true; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return \Monolog\Logger |
||||
*/ |
||||
public static function logger() |
||||
{ |
||||
static $result = null; |
||||
if (empty($result)) { |
||||
self::register_autoload(); |
||||
$name = Chamilo::name(); |
||||
$result = new Logger($name); |
||||
$handler = new Monolog\Handler\StreamHandler('php://stderr'); |
||||
$handler->setFormatter(new Monolog\Formatter\LineFormatter('[%datetime%] [%level_name%] [%channel%]: %message% %context% %extra%' . PHP_EOL, 'Y-m-d H:i:s')); |
||||
$result->pushHandler($handler); |
||||
//$result->pushProcessor(new \Monolog\Processor\WebProcessor()); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the DEBUG level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public static function debug($message, array $context = array()) |
||||
{ |
||||
return self::logger()->debug($message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the INFO level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public static function info($message, array $context = array()) |
||||
{ |
||||
return self::logger()->info($message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the INFO level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public static function notice($message, array $context = array()) |
||||
{ |
||||
return self::logger()->notice($message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the WARNING level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public static function warning($message, array $context = array()) |
||||
{ |
||||
return self::logger()->warn($message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the ERROR level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public static function error($message, array $context = array()) |
||||
{ |
||||
return self::logger()->err($message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the CRITICAL level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public static function crit($message, array $context = array()) |
||||
{ |
||||
return self::logger()->crit($message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the ALERT level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public static function alert($message, array $context = array()) |
||||
{ |
||||
return self::logger()->alert($message, $context); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,36 @@ |
||||
<?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\Formatter; |
||||
|
||||
/** |
||||
* Interface for formatters |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
interface FormatterInterface |
||||
{ |
||||
/** |
||||
* Formats a log record. |
||||
* |
||||
* @param array $record A record to format |
||||
* @return mixed The formatted record |
||||
*/ |
||||
function format(array $record); |
||||
|
||||
/** |
||||
* Formats a set of log records. |
||||
* |
||||
* @param array $records A set of records to format |
||||
* @return mixed The formatted set of records |
||||
*/ |
||||
function formatBatch(array $records); |
||||
} |
@ -0,0 +1,40 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Encodes whatever record data is passed to it as json |
||||
* |
||||
* This can be useful to log to databases or remote APIs |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
class JsonFormatter implements FormatterInterface |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function format(array $record) |
||||
{ |
||||
return json_encode($record); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function formatBatch(array $records) |
||||
{ |
||||
return json_encode($records); |
||||
} |
||||
} |
@ -0,0 +1,105 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Formats incoming records into a one-line string |
||||
* |
||||
* This is especially useful for logging to files |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
* @author Christophe Coevoet <stof@notk.org> |
||||
*/ |
||||
class LineFormatter implements FormatterInterface |
||||
{ |
||||
const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"; |
||||
const SIMPLE_DATE = "Y-m-d H:i:s"; |
||||
|
||||
protected $format; |
||||
protected $dateFormat; |
||||
|
||||
/** |
||||
* @param string $format The format of the message |
||||
* @param string $dateFormat The format of the timestamp: one supported by DateTime::format |
||||
*/ |
||||
public function __construct($format = null, $dateFormat = null) |
||||
{ |
||||
$this->format = $format ?: static::SIMPLE_FORMAT; |
||||
$this->dateFormat = $dateFormat ?: static::SIMPLE_DATE; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function format(array $record) |
||||
{ |
||||
$vars = $record; |
||||
$vars['datetime'] = $vars['datetime']->format($this->dateFormat); |
||||
|
||||
$output = $this->format; |
||||
foreach ($vars['extra'] as $var => $val) { |
||||
if (false !== strpos($output, '%extra.'.$var.'%')) { |
||||
$output = str_replace('%extra.'.$var.'%', $this->convertToString($val), $output); |
||||
unset($vars['extra'][$var]); |
||||
} |
||||
} |
||||
foreach ($vars as $var => $val) { |
||||
$output = str_replace('%'.$var.'%', $this->convertToString($val), $output); |
||||
} |
||||
|
||||
return $output; |
||||
} |
||||
|
||||
public function formatBatch(array $records) |
||||
{ |
||||
$message = ''; |
||||
foreach ($records as $record) { |
||||
$message .= $this->format($record); |
||||
} |
||||
|
||||
return $message; |
||||
} |
||||
|
||||
protected function convertToString($data) |
||||
{ |
||||
if (null === $data || is_scalar($data)) { |
||||
return (string) $data; |
||||
} |
||||
|
||||
return stripslashes(json_encode($this->normalize($data))); |
||||
} |
||||
|
||||
protected function normalize($data) |
||||
{ |
||||
if (null === $data || is_scalar($data)) { |
||||
return $data; |
||||
} |
||||
|
||||
if (is_array($data) || $data instanceof \Traversable) { |
||||
$normalized = array(); |
||||
|
||||
foreach ($data as $key => $value) { |
||||
$normalized[$key] = $this->normalize($value); |
||||
} |
||||
|
||||
return $normalized; |
||||
} |
||||
|
||||
if (is_resource($data)) { |
||||
return '[resource]'; |
||||
} |
||||
|
||||
return sprintf("[object] (%s: %s)", get_class($data), json_encode($data)); |
||||
} |
||||
} |
@ -0,0 +1,87 @@ |
||||
<?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\Formatter; |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Serializes a log message according to Wildfire's header requirements |
||||
* |
||||
* @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com> |
||||
* @author Christophe Coevoet <stof@notk.org> |
||||
* @author Kirill chEbba Chebunin <iam@chebba.org> |
||||
*/ |
||||
class WildfireFormatter implements FormatterInterface |
||||
{ |
||||
/** |
||||
* Translates Monolog log levels to Wildfire levels. |
||||
*/ |
||||
private $logLevels = array( |
||||
Logger::DEBUG => 'LOG', |
||||
Logger::INFO => 'INFO', |
||||
Logger::WARNING => 'WARN', |
||||
Logger::ERROR => 'ERROR', |
||||
Logger::CRITICAL => 'ERROR', |
||||
Logger::ALERT => 'ERROR', |
||||
); |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function format(array $record) |
||||
{ |
||||
// Retrieve the line and file if set and remove them from the formatted extra |
||||
$file = $line = ''; |
||||
if (isset($record['extra']['file'])) { |
||||
$file = $record['extra']['file']; |
||||
unset($record['extra']['file']); |
||||
} |
||||
if (isset($record['extra']['line'])) { |
||||
$line = $record['extra']['line']; |
||||
unset($record['extra']['line']); |
||||
} |
||||
|
||||
$message = array('message' => $record['message']); |
||||
if ($record['context']) { |
||||
$message['context'] = $record['context']; |
||||
} |
||||
if ($record['extra']) { |
||||
$message['extra'] = $record['extra']; |
||||
} |
||||
if (count($message) === 1) { |
||||
$message = reset($message); |
||||
} |
||||
|
||||
// Create JSON object describing the appearance of the message in the console |
||||
$json = json_encode(array( |
||||
array( |
||||
'Type' => $this->logLevels[$record['level']], |
||||
'File' => $file, |
||||
'Line' => $line, |
||||
'Label' => $record['channel'], |
||||
), |
||||
$message, |
||||
)); |
||||
|
||||
// The message itself is a serialization of the above JSON object + it's length |
||||
return sprintf( |
||||
'%s|%s|', |
||||
strlen($json), |
||||
$json |
||||
); |
||||
} |
||||
|
||||
public function formatBatch(array $records) |
||||
{ |
||||
throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter'); |
||||
} |
||||
} |
@ -0,0 +1,169 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of the Monolog package. |
||||
* |
||||
* (c) Jordi Boggiano <j.boggiano@seld.be> |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
namespace Monolog\Handler; |
||||
|
||||
use Monolog\Logger; |
||||
use Monolog\Formatter\FormatterInterface; |
||||
use Monolog\Formatter\LineFormatter; |
||||
|
||||
/** |
||||
* Base Handler class providing the Handler structure |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
abstract class AbstractHandler implements HandlerInterface |
||||
{ |
||||
protected $level = Logger::DEBUG; |
||||
protected $bubble = false; |
||||
|
||||
/** |
||||
* @var FormatterInterface |
||||
*/ |
||||
protected $formatter; |
||||
protected $processors = array(); |
||||
|
||||
/** |
||||
* @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($level = Logger::DEBUG, $bubble = true) |
||||
{ |
||||
$this->level = $level; |
||||
$this->bubble = $bubble; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function isHandling(array $record) |
||||
{ |
||||
return $record['level'] >= $this->level; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function handleBatch(array $records) |
||||
{ |
||||
foreach ($records as $record) { |
||||
$this->handle($record); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Closes the handler. |
||||
* |
||||
* This will be called automatically when the object is destroyed |
||||
*/ |
||||
public function close() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function pushProcessor($callback) |
||||
{ |
||||
if (!is_callable($callback)) { |
||||
throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given'); |
||||
} |
||||
array_unshift($this->processors, $callback); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function popProcessor() |
||||
{ |
||||
if (!$this->processors) { |
||||
throw new \LogicException('You tried to pop from an empty processor stack.'); |
||||
} |
||||
return array_shift($this->processors); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setFormatter(FormatterInterface $formatter) |
||||
{ |
||||
$this->formatter = $formatter; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getFormatter() |
||||
{ |
||||
if (!$this->formatter) { |
||||
$this->formatter = $this->getDefaultFormatter(); |
||||
} |
||||
|
||||
return $this->formatter; |
||||
} |
||||
|
||||
/** |
||||
* Sets minimum logging level at which this handler will be triggered. |
||||
* |
||||
* @param integer $level |
||||
*/ |
||||
public function setLevel($level) |
||||
{ |
||||
$this->level = $level; |
||||
} |
||||
|
||||
/** |
||||
* Gets minimum logging level at which this handler will be triggered. |
||||
* |
||||
* @return integer |
||||
*/ |
||||
public function getLevel() |
||||
{ |
||||
return $this->level; |
||||
} |
||||
|
||||
/** |
||||
* Sets the bubbling behavior. |
||||
* |
||||
* @param Boolean $bubble True means that bubbling is not permitted. |
||||
* False means that this handler allows bubbling. |
||||
*/ |
||||
public function setBubble($bubble) |
||||
{ |
||||
$this->bubble = $bubble; |
||||
} |
||||
|
||||
/** |
||||
* Gets the bubbling behavior. |
||||
* |
||||
* @return Boolean True means that bubbling is not permitted. |
||||
* False means that this handler allows bubbling. |
||||
*/ |
||||
public function getBubble() |
||||
{ |
||||
return $this->bubble; |
||||
} |
||||
|
||||
public function __destruct() |
||||
{ |
||||
$this->close(); |
||||
} |
||||
|
||||
/** |
||||
* Gets the default formatter. |
||||
* |
||||
* @return FormatterInterface |
||||
*/ |
||||
protected function getDefaultFormatter() |
||||
{ |
||||
return new LineFormatter(); |
||||
} |
||||
} |
@ -0,0 +1,70 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of the Monolog package. |
||||
* |
||||
* (c) Jordi Boggiano <j.boggiano@seld.be> |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
namespace Monolog\Handler; |
||||
|
||||
use Monolog\Logger; |
||||
use Monolog\Formatter\FormatterInterface; |
||||
use Monolog\Formatter\LineFormatter; |
||||
|
||||
/** |
||||
* Base Handler class providing the Handler structure |
||||
* |
||||
* Classes extending it should (in most cases) only implement write($record) |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
* @author Christophe Coevoet <stof@notk.org> |
||||
*/ |
||||
abstract class AbstractProcessingHandler extends AbstractHandler |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function handle(array $record) |
||||
{ |
||||
if ($record['level'] < $this->level) { |
||||
return false; |
||||
} |
||||
|
||||
$record = $this->processRecord($record); |
||||
|
||||
$record['formatted'] = $this->getFormatter()->format($record); |
||||
|
||||
$this->write($record); |
||||
|
||||
return false === $this->bubble; |
||||
} |
||||
|
||||
/** |
||||
* Writes the record down to the log of the implementing handler |
||||
* |
||||
* @param array $record |
||||
* @return void |
||||
*/ |
||||
abstract protected function write(array $record); |
||||
|
||||
/** |
||||
* Processes a record. |
||||
* |
||||
* @param array $record |
||||
* @return array |
||||
*/ |
||||
protected function processRecord(array $record) |
||||
{ |
||||
if ($this->processors) { |
||||
foreach ($this->processors as $processor) { |
||||
$record = call_user_func($processor, $record); |
||||
} |
||||
} |
||||
|
||||
return $record; |
||||
} |
||||
} |
@ -0,0 +1,67 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of the Monolog package. |
||||
* |
||||
* (c) Jordi Boggiano <j.boggiano@seld.be> |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
namespace Monolog\Handler; |
||||
|
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Buffers all records until closing the handler and then pass them as batch. |
||||
* |
||||
* This is useful for a MailHandler to send only one mail per request instead of |
||||
* sending one per log message. |
||||
* |
||||
* @author Christophe Coevoet <stof@notk.org> |
||||
*/ |
||||
class BufferHandler extends AbstractHandler |
||||
{ |
||||
protected $handler; |
||||
protected $bufferSize; |
||||
protected $buffer = array(); |
||||
|
||||
/** |
||||
* @param HandlerInterface $handler Handler. |
||||
* @param integer $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. |
||||
* @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(HandlerInterface $handler, $bufferSize = 0, $level = Logger::DEBUG, $bubble = true) |
||||
{ |
||||
parent::__construct($level, $bubble); |
||||
$this->handler = $handler; |
||||
$this->bufferSize = $bufferSize; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function handle(array $record) |
||||
{ |
||||
if ($record['level'] < $this->level) { |
||||
return false; |
||||
} |
||||
|
||||
$this->buffer[] = $record; |
||||
if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { |
||||
array_shift($this->buffer); |
||||
} |
||||
|
||||
return false === $this->bubble; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function close() |
||||
{ |
||||
$this->handler->handleBatch($this->buffer); |
||||
} |
||||
} |
@ -0,0 +1,95 @@ |
||||
<?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; |
||||
|
||||
/** |
||||
* Buffers all records until a certain level is reached |
||||
* |
||||
* The advantage of this approach is that you don't get any clutter in your log files. |
||||
* Only requests which actually trigger an error (or whatever your actionLevel is) will be |
||||
* in the logs, but they will contain all records, not only those above the level threshold. |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
class FingersCrossedHandler extends AbstractHandler |
||||
{ |
||||
protected $handler; |
||||
protected $actionLevel; |
||||
protected $buffering = true; |
||||
protected $bufferSize; |
||||
protected $buffer = array(); |
||||
protected $stopBuffering; |
||||
|
||||
/** |
||||
* @param callback|HandlerInterface $handler Handler or factory callback($record, $fingersCrossedHandler). |
||||
* @param int $actionLevel The minimum logging level at which this handler will be triggered |
||||
* @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. |
||||
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not |
||||
* @param Boolean $stopBuffering Whether the handler should stop buffering after being triggered (default true) |
||||
*/ |
||||
public function __construct($handler, $actionLevel = Logger::WARNING, $bufferSize = 0, $bubble = true, $stopBuffering = true) |
||||
{ |
||||
$this->handler = $handler; |
||||
$this->actionLevel = $actionLevel; |
||||
$this->bufferSize = $bufferSize; |
||||
$this->bubble = $bubble; |
||||
$this->stopBuffering = $stopBuffering; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function isHandling(array $record) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function handle(array $record) |
||||
{ |
||||
if ($this->buffering) { |
||||
$this->buffer[] = $record; |
||||
if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { |
||||
array_shift($this->buffer); |
||||
} |
||||
if ($record['level'] >= $this->actionLevel) { |
||||
if ($this->stopBuffering) { |
||||
$this->buffering = false; |
||||
} |
||||
if (!$this->handler instanceof HandlerInterface) { |
||||
$this->handler = call_user_func($this->handler, $record, $this); |
||||
} |
||||
if (!$this->handler instanceof HandlerInterface) { |
||||
throw new \RuntimeException("The factory callback should return a HandlerInterface"); |
||||
} |
||||
$this->handler->handleBatch($this->buffer); |
||||
$this->buffer = array(); |
||||
} |
||||
} else { |
||||
$this->handler->handle($record); |
||||
} |
||||
|
||||
return false === $this->bubble; |
||||
} |
||||
|
||||
/** |
||||
* Resets the state of the handler. Stops forwarding records to the wrapped handler. |
||||
*/ |
||||
public function reset() |
||||
{ |
||||
$this->buffering = true; |
||||
} |
||||
} |
@ -0,0 +1,159 @@ |
||||
<?php |
||||
|
||||
/* |
||||
* This file is part of the Monolog package. |
||||
* |
||||
* (c) Jordi Boggiano <j.boggiano@seld.be> |
||||
* |
||||
* For the full copyright and license information, please view the LICENSE |
||||
* file that was distributed with this source code. |
||||
*/ |
||||
|
||||
namespace Monolog\Handler; |
||||
|
||||
use Monolog\Logger; |
||||
use Monolog\Formatter\WildfireFormatter; |
||||
|
||||
/** |
||||
* Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol. |
||||
* |
||||
* @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com> |
||||
*/ |
||||
class FirePHPHandler extends AbstractProcessingHandler |
||||
{ |
||||
/** |
||||
* WildFire JSON header message format |
||||
*/ |
||||
const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2'; |
||||
|
||||
/** |
||||
* FirePHP structure for parsing messages & their presentation |
||||
*/ |
||||
const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'; |
||||
|
||||
/** |
||||
* Must reference a "known" plugin, otherwise headers won't display in FirePHP |
||||
*/ |
||||
const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3'; |
||||
|
||||
/** |
||||
* Header prefix for Wildfire to recognize & parse headers |
||||
*/ |
||||
const HEADER_PREFIX = 'X-Wf'; |
||||
|
||||
/** |
||||
* Whether or not Wildfire vendor-specific headers have been generated & sent yet |
||||
*/ |
||||
protected static $initialized = false; |
||||
|
||||
/** |
||||
* Shared static message index between potentially multiple handlers |
||||
* @var int |
||||
*/ |
||||
protected static $messageIndex = 1; |
||||
|
||||
protected $sendHeaders = true; |
||||
|
||||
/** |
||||
* Base header creation function used by init headers & record headers |
||||
* |
||||
* @param array $meta Wildfire Plugin, Protocol & Structure Indexes |
||||
* @param string $message Log message |
||||
* @return array Complete header string ready for the client as key and message as value |
||||
*/ |
||||
protected function createHeader(array $meta, $message) |
||||
{ |
||||
$header = sprintf('%s-%s', self::HEADER_PREFIX, join('-', $meta)); |
||||
|
||||
return array($header => $message); |
||||
} |
||||
|
||||
/** |
||||
* Creates message header from record |
||||
* |
||||
* @see createHeader() |
||||
* @param array $record |
||||
* @return string |
||||
*/ |
||||
protected function createRecordHeader(array $record) |
||||
{ |
||||
// Wildfire is extensible to support multiple protocols & plugins in a single request, |
||||
// but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake. |
||||
return $this->createHeader( |
||||
array(1, 1, 1, self::$messageIndex++), |
||||
$record['formatted'] |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
protected function getDefaultFormatter() |
||||
{ |
||||
return new WildfireFormatter(); |
||||
} |
||||
|
||||
/** |
||||
* Wildfire initialization headers to enable message parsing |
||||
* |
||||
* @see createHeader() |
||||
* @see sendHeader() |
||||
* @return array |
||||
*/ |
||||
protected function getInitHeaders() |
||||
{ |
||||
// Initial payload consists of required headers for Wildfire |
||||
return array_merge( |
||||
$this->createHeader(array('Protocol', 1), self::PROTOCOL_URI), |
||||
$this->createHeader(array(1, 'Structure', 1), self::STRUCTURE_URI), |
||||
$this->createHeader(array(1, 'Plugin', 1), self::PLUGIN_URI) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Send header string to the client |
||||
* |
||||
* @param string $header |
||||
* @param string $content |
||||
*/ |
||||
protected function sendHeader($header, $content) |
||||
{ |
||||
if (!headers_sent() && $this->sendHeaders) { |
||||
header(sprintf('%s: %s', $header, $content)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Creates & sends header for a record, ensuring init headers have been sent prior |
||||
* |
||||
* @see sendHeader() |
||||
* @see sendInitHeaders() |
||||
* @param array $record |
||||
*/ |
||||
protected function write(array $record) |
||||
{ |
||||
// WildFire-specific headers must be sent prior to any messages |
||||
if (!self::$initialized) { |
||||
$this->sendHeaders = $this->headersAccepted(); |
||||
|
||||
foreach ($this->getInitHeaders() as $header => $content) { |
||||
$this->sendHeader($header, $content); |
||||
} |
||||
|
||||
self::$initialized = true; |
||||
} |
||||
|
||||
$header = $this->createRecordHeader($record); |
||||
$this->sendHeader(key($header), current($header)); |
||||
} |
||||
|
||||
/** |
||||
* Verifies if the headers are accepted by the current user agent |
||||
* |
||||
* @return Boolean |
||||
*/ |
||||
protected function headersAccepted() |
||||
{ |
||||
return !isset($_SERVER['HTTP_USER_AGENT']) || preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT']); |
||||
} |
||||
} |
@ -0,0 +1,74 @@ |
||||
<?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; |
||||
|
||||
/** |
||||
* Forwards records to multiple handlers |
||||
* |
||||
* @author Lenar Lõhmus <lenar@city.ee> |
||||
*/ |
||||
class GroupHandler extends AbstractHandler |
||||
{ |
||||
protected $handlers; |
||||
|
||||
/** |
||||
* @param array $handlers Array of Handlers. |
||||
* @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not |
||||
*/ |
||||
public function __construct(array $handlers, $bubble = true) |
||||
{ |
||||
foreach ($handlers as $handler) { |
||||
if (!$handler instanceof HandlerInterface) { |
||||
throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.'); |
||||
} |
||||
} |
||||
|
||||
$this->handlers = $handlers; |
||||
$this->bubble = $bubble; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function isHandling(array $record) |
||||
{ |
||||
foreach ($this->handlers as $handler) { |
||||
if ($handler->isHandling($record)) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function handle(array $record) |
||||
{ |
||||
foreach ($this->handlers as $handler) { |
||||
$handler->handle($record); |
||||
} |
||||
|
||||
return false === $this->bubble; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function handleBatch(array $records) |
||||
{ |
||||
foreach ($this->handlers as $handler) { |
||||
$handler->handleBatch($records); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,77 @@ |
||||
<?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\Formatter\FormatterInterface; |
||||
|
||||
/** |
||||
* Interface that all Monolog Handlers must implement |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
interface HandlerInterface |
||||
{ |
||||
/** |
||||
* Checks whether the given record will be handled by this handler. |
||||
* |
||||
* This is mostly done for performance reasons, to avoid calling processors for nothing. |
||||
* |
||||
* @return Boolean |
||||
*/ |
||||
function isHandling(array $record); |
||||
|
||||
/** |
||||
* Handles a record. |
||||
* |
||||
* The return value of this function controls the bubbling process of the handler stack. |
||||
* |
||||
* @param array $record The record to handle |
||||
* @return Boolean True means that this handler handled the record, and that bubbling is not permitted. |
||||
* False means the record was either not processed or that this handler allows bubbling. |
||||
*/ |
||||
function handle(array $record); |
||||
|
||||
/** |
||||
* Handles a set of records at once. |
||||
* |
||||
* @param array $records The records to handle (an array of record arrays) |
||||
*/ |
||||
function handleBatch(array $records); |
||||
|
||||
/** |
||||
* Adds a processor in the stack. |
||||
* |
||||
* @param callable $callback |
||||
*/ |
||||
function pushProcessor($callback); |
||||
|
||||
/** |
||||
* Removes the processor on top of the stack and returns it. |
||||
* |
||||
* @return callable |
||||
*/ |
||||
function popProcessor(); |
||||
|
||||
/** |
||||
* Sets the formatter. |
||||
* |
||||
* @param FormatterInterface $formatter |
||||
*/ |
||||
function setFormatter(FormatterInterface $formatter); |
||||
|
||||
/** |
||||
* Gets the formatter. |
||||
* |
||||
* @return FormatterInterface |
||||
*/ |
||||
function getFormatter(); |
||||
} |
@ -0,0 +1,54 @@ |
||||
<?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; |
||||
|
||||
/** |
||||
* Base class for all mail handlers |
||||
* |
||||
* @author Gyula Sallai |
||||
*/ |
||||
abstract class MailHandler extends AbstractProcessingHandler |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function handleBatch(array $records) |
||||
{ |
||||
$messages = array(); |
||||
|
||||
foreach ($records as $record) { |
||||
if ($record['level'] < $this->level) { |
||||
continue; |
||||
} |
||||
$messages[] = $this->processRecord($record); |
||||
} |
||||
|
||||
if (!empty($messages)) { |
||||
$this->send((string) $this->getFormatter()->formatBatch($messages)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Send a mail with the given content |
||||
* |
||||
* @param string $content |
||||
*/ |
||||
abstract protected function send($content); |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function write(array $record) |
||||
{ |
||||
$this->send((string) $record['formatted']); |
||||
} |
||||
} |
@ -0,0 +1,49 @@ |
||||
<?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; |
||||
|
||||
/** |
||||
* NativeMailerHandler uses the mail() function to send the emails |
||||
* |
||||
* @author Christophe Coevoet <stof@notk.org> |
||||
*/ |
||||
class NativeMailerHandler extends MailHandler |
||||
{ |
||||
protected $to; |
||||
protected $subject; |
||||
protected $headers; |
||||
|
||||
/** |
||||
* @param string $to The receiver of the mail |
||||
* @param string $subject The subject of the mail |
||||
* @param string $from The sender of the mail |
||||
* @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($to, $subject, $from, $level = Logger::ERROR, $bubble = true) |
||||
{ |
||||
parent::__construct($level, $bubble); |
||||
$this->to = $to; |
||||
$this->subject = $subject; |
||||
$this->headers = sprintf("From: %s\r\nContent-type: text/plain; charset=utf-8\r\n", $from); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function send($content) |
||||
{ |
||||
mail($this->to, $this->subject, wordwrap($content, 70), $this->headers); |
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
<?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; |
||||
|
||||
/** |
||||
* Blackhole |
||||
* |
||||
* Any record it can handle will be thrown away. This can be used |
||||
* to put on top of an existing stack to override it temporarily. |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
class NullHandler extends AbstractHandler |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function handle(array $record) |
||||
{ |
||||
if ($record['level'] < $this->level) { |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,109 @@ |
||||
<?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 logs to files that are rotated every day and a limited number of files are kept. |
||||
* |
||||
* This rotation is only intended to be used as a workaround. Using logrotate to |
||||
* handle the rotation is strongly encouraged when you can use it. |
||||
* |
||||
* @author Christophe Coevoet <stof@notk.org> |
||||
*/ |
||||
class RotatingFileHandler extends StreamHandler |
||||
{ |
||||
protected $filename; |
||||
protected $maxFiles; |
||||
protected $mustRotate; |
||||
|
||||
/** |
||||
* @param string $filename |
||||
* @param integer $maxFiles The maximal amount of files to keep (0 means unlimited) |
||||
* @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($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true) |
||||
{ |
||||
$this->filename = $filename; |
||||
$this->maxFiles = (int) $maxFiles; |
||||
|
||||
$fileInfo = pathinfo($this->filename); |
||||
$timedFilename = $fileInfo['dirname'].'/'.$fileInfo['filename'].'-'.date('Y-m-d'); |
||||
if (!empty($fileInfo['extension'])) { |
||||
$timedFilename .= '.'.$fileInfo['extension']; |
||||
} |
||||
|
||||
// disable rotation upfront if files are unlimited |
||||
if (0 === $this->maxFiles) { |
||||
$this->mustRotate = false; |
||||
} |
||||
|
||||
parent::__construct($timedFilename, $level, $bubble); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function close() |
||||
{ |
||||
parent::close(); |
||||
|
||||
if (true === $this->mustRotate) { |
||||
$this->rotate(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function write(array $record) |
||||
{ |
||||
// on the first record written, if the log is new, we should rotate (once per day) |
||||
if (null === $this->mustRotate) { |
||||
$this->mustRotate = !file_exists($this->url); |
||||
} |
||||
|
||||
parent::write($record); |
||||
} |
||||
|
||||
/** |
||||
* Rotates the files. |
||||
*/ |
||||
protected function rotate() |
||||
{ |
||||
$fileInfo = pathinfo($this->filename); |
||||
$glob = $fileInfo['dirname'].'/'.$fileInfo['filename'].'-*'; |
||||
if (!empty($fileInfo['extension'])) { |
||||
$glob .= '.'.$fileInfo['extension']; |
||||
} |
||||
$iterator = new \GlobIterator($glob); |
||||
$count = $iterator->count(); |
||||
if ($this->maxFiles >= $count) { |
||||
// no files to remove |
||||
return; |
||||
} |
||||
|
||||
// Sorting the files by name to remove the older ones |
||||
$array = iterator_to_array($iterator); |
||||
usort($array, function($a, $b) { |
||||
return strcmp($b->getFilename(), $a->getFilename()); |
||||
}); |
||||
|
||||
foreach (array_slice($array, $this->maxFiles) as $file) { |
||||
if ($file->isWritable()) { |
||||
unlink($file->getRealPath()); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,72 @@ |
||||
<?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\Formatter\SimpleFormatter; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Stores to any stream resource |
||||
* |
||||
* Can be used to store into php://stderr, remote and local files, etc. |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
class StreamHandler extends AbstractProcessingHandler |
||||
{ |
||||
protected $stream; |
||||
protected $url; |
||||
|
||||
/** |
||||
* @param string $stream |
||||
* @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($stream, $level = Logger::DEBUG, $bubble = true) |
||||
{ |
||||
parent::__construct($level, $bubble); |
||||
if (is_resource($stream)) { |
||||
$this->stream = $stream; |
||||
} else { |
||||
$this->url = $stream; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function close() |
||||
{ |
||||
if (is_resource($this->stream)) { |
||||
fclose($this->stream); |
||||
} |
||||
$this->stream = null; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function write(array $record) |
||||
{ |
||||
if (null === $this->stream) { |
||||
if (!$this->url) { |
||||
throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().'); |
||||
} |
||||
$this->stream = @fopen($this->url, 'a'); |
||||
if (!is_resource($this->stream)) { |
||||
$this->stream = null; |
||||
throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened; it may be invalid or not writable.', $this->url)); |
||||
} |
||||
} |
||||
fwrite($this->stream, (string) $record['formatted']); |
||||
} |
||||
} |
@ -0,0 +1,55 @@ |
||||
<?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; |
||||
|
||||
/** |
||||
* SwiftMailerHandler uses Swift_Mailer to send the emails |
||||
* |
||||
* @author Gyula Sallai |
||||
*/ |
||||
class SwiftMailerHandler extends MailHandler |
||||
{ |
||||
protected $mailer; |
||||
protected $message; |
||||
|
||||
/** |
||||
* @param \Swift_Mailer $mailer The mailer to use |
||||
* @param callback|\Swift_Message $message An example message for real messages, only the body will be replaced |
||||
* @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(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true) |
||||
{ |
||||
parent::__construct($level, $bubble); |
||||
$this->mailer = $mailer; |
||||
if (!$message instanceof \Swift_Message && is_callable($message)) { |
||||
$message = call_user_func($message); |
||||
} |
||||
if (!$message instanceof \Swift_Message) { |
||||
throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callback returning it'); |
||||
} |
||||
$this->message = $message; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function send($content) |
||||
{ |
||||
$message = clone $this->message; |
||||
$message->setBody($content); |
||||
|
||||
$this->mailer->send($message); |
||||
} |
||||
} |
@ -0,0 +1,109 @@ |
||||
<?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\Formatter\SimpleFormatter; |
||||
use Monolog\Logger; |
||||
|
||||
/** |
||||
* Logs to syslog service. |
||||
* |
||||
* usage example: |
||||
* |
||||
* $log = new Logger('application'); |
||||
* $syslog = new SyslogHandler('myfacility', 'local6'); |
||||
* $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%"); |
||||
* $syslog->setFormatter($formatter); |
||||
* $log->pushHandler($syslog); |
||||
* |
||||
* @author Sven Paulus <sven@karlsruhe.org> |
||||
*/ |
||||
class SyslogHandler extends AbstractProcessingHandler |
||||
{ |
||||
/** |
||||
* Translates Monolog log levels to syslog log priorities. |
||||
*/ |
||||
private $logLevels = array( |
||||
Logger::DEBUG => LOG_DEBUG, |
||||
Logger::INFO => LOG_INFO, |
||||
Logger::WARNING => LOG_WARNING, |
||||
Logger::ERROR => LOG_ERR, |
||||
Logger::CRITICAL => LOG_CRIT, |
||||
Logger::ALERT => LOG_ALERT, |
||||
); |
||||
|
||||
/** |
||||
* List of valid log facility names. |
||||
*/ |
||||
private $facilities = array( |
||||
'auth' => LOG_AUTH, |
||||
'authpriv' => LOG_AUTHPRIV, |
||||
'cron' => LOG_CRON, |
||||
'daemon' => LOG_DAEMON, |
||||
'kern' => LOG_KERN, |
||||
'lpr' => LOG_LPR, |
||||
'mail' => LOG_MAIL, |
||||
'news' => LOG_NEWS, |
||||
'syslog' => LOG_SYSLOG, |
||||
'user' => LOG_USER, |
||||
'uucp' => LOG_UUCP, |
||||
); |
||||
|
||||
/** |
||||
* @param string $ident |
||||
* @param mixed $facility |
||||
* @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($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) |
||||
{ |
||||
parent::__construct($level, $bubble); |
||||
|
||||
if (!defined('PHP_WINDOWS_VERSION_BUILD')) { |
||||
$this->facilities['local0'] = LOG_LOCAL0; |
||||
$this->facilities['local1'] = LOG_LOCAL1; |
||||
$this->facilities['local2'] = LOG_LOCAL2; |
||||
$this->facilities['local3'] = LOG_LOCAL3; |
||||
$this->facilities['local4'] = LOG_LOCAL4; |
||||
$this->facilities['local5'] = LOG_LOCAL5; |
||||
$this->facilities['local6'] = LOG_LOCAL6; |
||||
$this->facilities['local7'] = LOG_LOCAL7; |
||||
} |
||||
|
||||
// convert textual description of facility to syslog constant |
||||
if (array_key_exists(strtolower($facility), $this->facilities)) { |
||||
$facility = $this->facilities[strtolower($facility)]; |
||||
} else if (!in_array($facility, array_values($this->facilities), true)) { |
||||
throw new \UnexpectedValueException('Unknown facility value "'.$facility.'" given'); |
||||
} |
||||
|
||||
if (!openlog($ident, LOG_PID, $facility)) { |
||||
throw new \LogicException('Can\'t open syslog for ident "'.$ident.'" and facility "'.$facility.'"'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function close() |
||||
{ |
||||
closelog(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function write(array $record) |
||||
{ |
||||
syslog($this->logLevels[$record['level']], (string) $record['formatted']); |
||||
} |
||||
} |
@ -0,0 +1,120 @@ |
||||
<?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; |
||||
|
||||
/** |
||||
* Used for testing purposes. |
||||
* |
||||
* It records all records and gives you access to them for verification. |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
class TestHandler extends AbstractProcessingHandler |
||||
{ |
||||
protected $records = array(); |
||||
protected $recordsByLevel = array(); |
||||
|
||||
public function getRecords() |
||||
{ |
||||
return $this->records; |
||||
} |
||||
|
||||
public function hasAlert($record) |
||||
{ |
||||
return $this->hasRecord($record, Logger::ALERT); |
||||
} |
||||
|
||||
public function hasCritical($record) |
||||
{ |
||||
return $this->hasRecord($record, Logger::CRITICAL); |
||||
} |
||||
|
||||
public function hasError($record) |
||||
{ |
||||
return $this->hasRecord($record, Logger::ERROR); |
||||
} |
||||
|
||||
public function hasWarning($record) |
||||
{ |
||||
return $this->hasRecord($record, Logger::WARNING); |
||||
} |
||||
|
||||
public function hasInfo($record) |
||||
{ |
||||
return $this->hasRecord($record, Logger::INFO); |
||||
} |
||||
|
||||
public function hasDebug($record) |
||||
{ |
||||
return $this->hasRecord($record, Logger::DEBUG); |
||||
} |
||||
|
||||
public function hasAlertRecords() |
||||
{ |
||||
return isset($this->recordsByLevel[Logger::ALERT]); |
||||
} |
||||
|
||||
public function hasCriticalRecords() |
||||
{ |
||||
return isset($this->recordsByLevel[Logger::CRITICAL]); |
||||
} |
||||
|
||||
public function hasErrorRecords() |
||||
{ |
||||
return isset($this->recordsByLevel[Logger::ERROR]); |
||||
} |
||||
|
||||
public function hasWarningRecords() |
||||
{ |
||||
return isset($this->recordsByLevel[Logger::WARNING]); |
||||
} |
||||
|
||||
public function hasInfoRecords() |
||||
{ |
||||
return isset($this->recordsByLevel[Logger::INFO]); |
||||
} |
||||
|
||||
public function hasDebugRecords() |
||||
{ |
||||
return isset($this->recordsByLevel[Logger::DEBUG]); |
||||
} |
||||
|
||||
protected function hasRecord($record, $level) |
||||
{ |
||||
if (!isset($this->recordsByLevel[$level])) { |
||||
return false; |
||||
} |
||||
|
||||
if (is_array($record)) { |
||||
$record = $record['message']; |
||||
} |
||||
|
||||
foreach ($this->recordsByLevel[$level] as $rec) { |
||||
if ($rec['message'] === $record) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function write(array $record) |
||||
{ |
||||
$this->recordsByLevel[$record['level']][] = $record; |
||||
$this->records[] = $record; |
||||
} |
||||
} |
@ -0,0 +1,394 @@ |
||||
<?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; |
||||
|
||||
use Monolog\Handler\HandlerInterface; |
||||
use Monolog\Handler\StreamHandler; |
||||
|
||||
/** |
||||
* Monolog log channel |
||||
* |
||||
* It contains a stack of Handlers and a stack of Processors, |
||||
* and uses them to store records that are added to it. |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
class Logger |
||||
{ |
||||
/** |
||||
* Detailed debug information |
||||
*/ |
||||
const DEBUG = 100; |
||||
|
||||
/** |
||||
* Interesting events |
||||
* |
||||
* Examples: User logs in, SQL logs. |
||||
*/ |
||||
const INFO = 200; |
||||
|
||||
/** |
||||
* Exceptional occurences that are not errors |
||||
* |
||||
* Examples: Use of deprecated APIs, poor use of an API, |
||||
* undesirable things that are not necessarily wrong. |
||||
*/ |
||||
const WARNING = 300; |
||||
|
||||
/** |
||||
* Runtime errors |
||||
*/ |
||||
const ERROR = 400; |
||||
|
||||
/** |
||||
* Critical conditions |
||||
* |
||||
* Example: Application component unavailable, unexpected exception. |
||||
*/ |
||||
const CRITICAL = 500; |
||||
|
||||
/** |
||||
* Action must be taken immediately |
||||
* |
||||
* Example: Entire website down, database unavailable, etc. |
||||
* This should trigger the SMS alerts and wake you up. |
||||
*/ |
||||
const ALERT = 550; |
||||
|
||||
protected static $levels = array( |
||||
100 => 'DEBUG', |
||||
200 => 'INFO', |
||||
300 => 'WARNING', |
||||
400 => 'ERROR', |
||||
500 => 'CRITICAL', |
||||
550 => 'ALERT', |
||||
); |
||||
|
||||
protected $name; |
||||
|
||||
/** |
||||
* The handler stack |
||||
* |
||||
* @var array of Monolog\Handler\HandlerInterface |
||||
*/ |
||||
protected $handlers = array(); |
||||
|
||||
protected $processors = array(); |
||||
|
||||
/** |
||||
* @param string $name The logging channel |
||||
*/ |
||||
public function __construct($name) |
||||
{ |
||||
$this->name = $name; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return $this->name; |
||||
} |
||||
|
||||
/** |
||||
* Pushes an handler on the stack. |
||||
* |
||||
* @param HandlerInterface $handler |
||||
*/ |
||||
public function pushHandler(HandlerInterface $handler) |
||||
{ |
||||
array_unshift($this->handlers, $handler); |
||||
} |
||||
|
||||
/** |
||||
* Pops an handler from the stack |
||||
* |
||||
* @return HandlerInterface |
||||
*/ |
||||
public function popHandler() |
||||
{ |
||||
if (!$this->handlers) { |
||||
throw new \LogicException('You tried to pop from an empty handler stack.'); |
||||
} |
||||
return array_shift($this->handlers); |
||||
} |
||||
|
||||
/** |
||||
* Adds a processor in the stack. |
||||
* |
||||
* @param callable $callback |
||||
*/ |
||||
public function pushProcessor($callback) |
||||
{ |
||||
if (!is_callable($callback)) { |
||||
throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given'); |
||||
} |
||||
array_unshift($this->processors, $callback); |
||||
} |
||||
|
||||
/** |
||||
* Removes the processor on top of the stack and returns it. |
||||
* |
||||
* @return callable |
||||
*/ |
||||
public function popProcessor() |
||||
{ |
||||
if (!$this->processors) { |
||||
throw new \LogicException('You tried to pop from an empty processor stack.'); |
||||
} |
||||
return array_shift($this->processors); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record. |
||||
* |
||||
* @param integer $level The logging level |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function addRecord($level, $message, array $context = array()) |
||||
{ |
||||
if (!$this->handlers) { |
||||
$this->pushHandler(new StreamHandler('php://stderr', self::DEBUG)); |
||||
} |
||||
$record = array( |
||||
'message' => (string) $message, |
||||
'context' => $context, |
||||
'level' => $level, |
||||
'level_name' => self::getLevelName($level), |
||||
'channel' => $this->name, |
||||
'datetime' => new \DateTime(), |
||||
'extra' => array(), |
||||
); |
||||
// check if any message will handle this message |
||||
$handlerKey = null; |
||||
foreach ($this->handlers as $key => $handler) { |
||||
if ($handler->isHandling($record)) { |
||||
$handlerKey = $key; |
||||
break; |
||||
} |
||||
} |
||||
// none found |
||||
if (null === $handlerKey) { |
||||
return false; |
||||
} |
||||
// found at least one, process message and dispatch it |
||||
foreach ($this->processors as $processor) { |
||||
$record = call_user_func($processor, $record); |
||||
} |
||||
while (isset($this->handlers[$handlerKey]) && |
||||
false === $this->handlers[$handlerKey]->handle($record)) { |
||||
$handlerKey++; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the DEBUG level. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function addDebug($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::DEBUG, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the INFO level. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function addInfo($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::INFO, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the WARNING level. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function addWarning($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::WARNING, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the ERROR level. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function addError($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::ERROR, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the CRITICAL level. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function addCritical($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::CRITICAL, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the ALERT level. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function addAlert($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::ALERT, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Gets the name of the logging level. |
||||
* |
||||
* @param integer $level |
||||
* @return string |
||||
*/ |
||||
public static function getLevelName($level) |
||||
{ |
||||
return self::$levels[$level]; |
||||
} |
||||
|
||||
// ZF Logger Compat |
||||
|
||||
/** |
||||
* Adds a log record at the DEBUG level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function debug($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::DEBUG, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the INFO level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function info($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::INFO, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the INFO level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function notice($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::INFO, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the WARNING level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function warn($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::WARNING, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the ERROR level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function err($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::ERROR, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the CRITICAL level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function crit($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::CRITICAL, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the ALERT level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function alert($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::ALERT, $message, $context); |
||||
} |
||||
|
||||
/** |
||||
* Adds a log record at the ALERT level. |
||||
* |
||||
* This method allows to have an easy ZF compatibility. |
||||
* |
||||
* @param string $message The log message |
||||
* @param array $context The log context |
||||
* @return Boolean Whether the record has been processed |
||||
*/ |
||||
public function emerg($message, array $context = array()) |
||||
{ |
||||
return $this->addRecord(self::ALERT, $message, $context); |
||||
} |
||||
} |
@ -0,0 +1,58 @@ |
||||
<?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\Processor; |
||||
|
||||
/** |
||||
* Injects line/file:class/function where the log message came from |
||||
* |
||||
* Warning: This only works if the handler processes the logs directly. |
||||
* If you put the processor on a handler that is behind a FingersCrossedHandler |
||||
* for example, the processor will only be called once the trigger level is reached, |
||||
* and all the log records will have the same file/line/.. data from the call that |
||||
* triggered the FingersCrossedHandler. |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
class IntrospectionProcessor |
||||
{ |
||||
/** |
||||
* @param array $record |
||||
* @return array |
||||
*/ |
||||
public function __invoke(array $record) |
||||
{ |
||||
$trace = debug_backtrace(); |
||||
|
||||
// skip first since it's always the current method |
||||
array_shift($trace); |
||||
// the call_user_func call is also skipped |
||||
array_shift($trace); |
||||
|
||||
$i = 0; |
||||
while (isset($trace[$i]['class']) && false !== strpos($trace[$i]['class'], 'Monolog\\')) { |
||||
$i++; |
||||
} |
||||
|
||||
// we should have the call source now |
||||
$record['extra'] = array_merge( |
||||
$record['extra'], |
||||
array( |
||||
'file' => isset($trace[$i-1]['file']) ? $trace[$i-1]['file'] : null, |
||||
'line' => isset($trace[$i-1]['line']) ? $trace[$i-1]['line'] : null, |
||||
'class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : null, |
||||
'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null, |
||||
) |
||||
); |
||||
|
||||
return $record; |
||||
} |
||||
} |
@ -0,0 +1,40 @@ |
||||
<?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\Processor; |
||||
|
||||
/** |
||||
* Injects memory_get_peak_usage in all records |
||||
* |
||||
* @see Monolog\Processor\MemoryProcessor::__construct() for options |
||||
* @author Rob Jensen |
||||
*/ |
||||
class MemoryPeakUsageProcessor extends MemoryProcessor |
||||
{ |
||||
/** |
||||
* @param array $record |
||||
* @return array |
||||
*/ |
||||
public function __invoke(array $record) |
||||
{ |
||||
$bytes = memory_get_peak_usage($this->realUsage); |
||||
$formatted = self::formatBytes($bytes); |
||||
|
||||
$record['extra'] = array_merge( |
||||
$record['extra'], |
||||
array( |
||||
'memory_peak_usage' => $formatted, |
||||
) |
||||
); |
||||
|
||||
return $record; |
||||
} |
||||
} |
@ -0,0 +1,50 @@ |
||||
<?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\Processor; |
||||
|
||||
/** |
||||
* Some methods that are common for all memory processors |
||||
* |
||||
* @author Rob Jensen |
||||
*/ |
||||
abstract class MemoryProcessor |
||||
{ |
||||
protected $realUsage; |
||||
|
||||
/** |
||||
* @param boolean $realUsage |
||||
*/ |
||||
public function __construct($realUsage = true) |
||||
{ |
||||
$this->realUsage = (boolean) $realUsage; |
||||
} |
||||
|
||||
/** |
||||
* Formats bytes into a human readable string |
||||
* |
||||
* @param int $bytes |
||||
* @return string |
||||
*/ |
||||
protected static function formatBytes($bytes) |
||||
{ |
||||
$bytes = (int) $bytes; |
||||
|
||||
if ($bytes > 1024*1024) { |
||||
return round($bytes/1024/1024, 2).' MB'; |
||||
} elseif ($bytes > 1024) { |
||||
return round($bytes/1024, 2).' KB'; |
||||
} |
||||
|
||||
return $bytes . ' B'; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,40 @@ |
||||
<?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\Processor; |
||||
|
||||
/** |
||||
* Injects memory_get_usage in all records |
||||
* |
||||
* @see Monolog\Processor\MemoryProcessor::__construct() for options |
||||
* @author Rob Jensen |
||||
*/ |
||||
class MemoryUsageProcessor extends MemoryProcessor |
||||
{ |
||||
/** |
||||
* @param array $record |
||||
* @return array |
||||
*/ |
||||
public function __invoke(array $record) |
||||
{ |
||||
$bytes = memory_get_usage($this->realUsage); |
||||
$formatted = self::formatBytes($bytes); |
||||
|
||||
$record['extra'] = array_merge( |
||||
$record['extra'], |
||||
array( |
||||
'memory_usage' => $formatted, |
||||
) |
||||
); |
||||
|
||||
return $record; |
||||
} |
||||
} |
@ -0,0 +1,60 @@ |
||||
<?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\Processor; |
||||
|
||||
/** |
||||
* Injects url/method and remote IP of the current web request in all records |
||||
* |
||||
* @author Jordi Boggiano <j.boggiano@seld.be> |
||||
*/ |
||||
class WebProcessor |
||||
{ |
||||
protected $serverData; |
||||
|
||||
/** |
||||
* @param mixed $serverData array or object w/ ArrayAccess that provides access to the $_SERVER data |
||||
*/ |
||||
public function __construct($serverData = null) |
||||
{ |
||||
if (null === $serverData) { |
||||
$this->serverData =& $_SERVER; |
||||
} elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) { |
||||
$this->serverData = $serverData; |
||||
} else { |
||||
throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @param array $record |
||||
* @return array |
||||
*/ |
||||
public function __invoke(array $record) |
||||
{ |
||||
// skip processing if for some reason request data |
||||
// is not present (CLI or wonky SAPIs) |
||||
if (!isset($this->serverData['REQUEST_URI'])) { |
||||
return $record; |
||||
} |
||||
|
||||
$record['extra'] = array_merge( |
||||
$record['extra'], |
||||
array( |
||||
'url' => $this->serverData['REQUEST_URI'], |
||||
'ip' => $this->serverData['REMOTE_ADDR'], |
||||
'http_method' => $this->serverData['REQUEST_METHOD'], |
||||
) |
||||
); |
||||
|
||||
return $record; |
||||
} |
||||
} |
@ -0,0 +1,16 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* Description of install |
||||
* |
||||
* @license see /license.txt |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
*/ |
||||
class Install |
||||
{ |
||||
static function message($message) |
||||
{ |
||||
echo '<div>' . $message . '</div>'; |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue