diff --git a/.travis.yml b/.travis.yml
index b821b452..07bad617 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,7 +9,7 @@ php:
- 5.6
- 7.0
- 7.1
- - hhvm
+ - 7.2
- nightly
matrix:
diff --git a/README.md b/README.md
index 7d8ade52..d7569446 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,6 @@
[](https://packagist.org/packages/monolog/monolog)
[](https://packagist.org/packages/monolog/monolog)
-[](https://www.versioneye.com/php/monolog:monolog/references)
Monolog sends your logs to files, sockets, inboxes, databases and various
diff --git a/doc/02-handlers-formatters-processors.md b/doc/02-handlers-formatters-processors.md
index bea968ac..af45913a 100644
--- a/doc/02-handlers-formatters-processors.md
+++ b/doc/02-handlers-formatters-processors.md
@@ -55,6 +55,7 @@
- _RollbarHandler_: Logs records to a [Rollbar](https://rollbar.com/) account.
- _SyslogUdpHandler_: Logs records to a remote [Syslogd](http://www.rsyslog.com/) server.
- _LogEntriesHandler_: Logs records to a [LogEntries](http://logentries.com/) account.
+- _InsightOpsHandler_: Logs records to a [InsightOps](https://www.rapid7.com/products/insightops/) account.
### Logging in development
diff --git a/src/Monolog/ErrorHandler.php b/src/Monolog/ErrorHandler.php
index f0ff3d8c..b96c58ae 100644
--- a/src/Monolog/ErrorHandler.php
+++ b/src/Monolog/ErrorHandler.php
@@ -39,6 +39,7 @@ class ErrorHandler
private $hasFatalErrorHandler;
private $fatalLevel;
private $reservedMemory;
+ private $lastFatalTrace;
private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR);
private $previousSignalHandler = array();
@@ -192,6 +193,13 @@ class ErrorHandler
if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) {
$level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL;
$this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line));
+ } else {
+ // http://php.net/manual/en/function.debug-backtrace.php
+ // As of 5.3.6, DEBUG_BACKTRACE_IGNORE_ARGS option was added.
+ // Any version less than 5.3.6 must use the DEBUG_BACKTRACE_IGNORE_ARGS constant value '2'.
+ $trace = debug_backtrace((PHP_VERSION_ID < 50306) ? 2 : DEBUG_BACKTRACE_IGNORE_ARGS);
+ array_shift($trace); // Exclude handleError from trace
+ $this->lastFatalTrace = $trace;
}
if ($this->previousErrorHandler === true) {
@@ -213,7 +221,7 @@ class ErrorHandler
$this->logger->log(
$this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel,
'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'],
- array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'])
+ array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace)
);
if ($this->logger instanceof Logger) {
diff --git a/src/Monolog/Formatter/FluentdFormatter.php b/src/Monolog/Formatter/FluentdFormatter.php
index 02632bb5..46a91ffe 100644
--- a/src/Monolog/Formatter/FluentdFormatter.php
+++ b/src/Monolog/Formatter/FluentdFormatter.php
@@ -62,6 +62,7 @@ class FluentdFormatter implements FormatterInterface
$message = array(
'message' => $record['message'],
+ 'context' => $record['context'],
'extra' => $record['extra'],
);
diff --git a/src/Monolog/Formatter/HtmlFormatter.php b/src/Monolog/Formatter/HtmlFormatter.php
index 3eec95f6..dfc0b4a3 100644
--- a/src/Monolog/Formatter/HtmlFormatter.php
+++ b/src/Monolog/Formatter/HtmlFormatter.php
@@ -58,7 +58,7 @@ class HtmlFormatter extends NormalizerFormatter
$td = '
'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'
';
}
- return "\n$th: | \n".$td." | \n
";
+ return "\n$th: | \n".$td." | \n
";
}
/**
diff --git a/src/Monolog/Formatter/JsonFormatter.php b/src/Monolog/Formatter/JsonFormatter.php
index 0782f149..b8309b10 100644
--- a/src/Monolog/Formatter/JsonFormatter.php
+++ b/src/Monolog/Formatter/JsonFormatter.php
@@ -138,18 +138,23 @@ class JsonFormatter extends NormalizerFormatter
*
* @return mixed
*/
- protected function normalize($data)
+ protected function normalize($data, $depth = 0)
{
+ if ($depth > 9) {
+ return 'Over 9 levels deep, aborting normalization';
+ }
+
if (is_array($data) || $data instanceof \Traversable) {
$normalized = array();
$count = 1;
foreach ($data as $key => $value) {
- if ($count++ >= 1000) {
- $normalized['...'] = 'Over 1000 items, aborting normalization';
+ if ($count++ > 1000) {
+ $normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization';
break;
}
- $normalized[$key] = $this->normalize($value);
+
+ $normalized[$key] = $this->normalize($value, $depth+1);
}
return $normalized;
diff --git a/src/Monolog/Formatter/NormalizerFormatter.php b/src/Monolog/Formatter/NormalizerFormatter.php
index d4414882..91227241 100644
--- a/src/Monolog/Formatter/NormalizerFormatter.php
+++ b/src/Monolog/Formatter/NormalizerFormatter.php
@@ -55,8 +55,12 @@ class NormalizerFormatter implements FormatterInterface
return $records;
}
- protected function normalize($data)
+ protected function normalize($data, $depth = 0)
{
+ if ($depth > 9) {
+ return 'Over 9 levels deep, aborting normalization';
+ }
+
if (null === $data || is_scalar($data)) {
if (is_float($data)) {
if (is_infinite($data)) {
@@ -75,11 +79,12 @@ class NormalizerFormatter implements FormatterInterface
$count = 1;
foreach ($data as $key => $value) {
- if ($count++ >= 1000) {
+ if ($count++ > 1000) {
$normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization';
break;
}
- $normalized[$key] = $this->normalize($value);
+
+ $normalized[$key] = $this->normalize($value, $depth+1);
}
return $normalized;
diff --git a/src/Monolog/Formatter/WildfireFormatter.php b/src/Monolog/Formatter/WildfireFormatter.php
index 654710a8..65dba99c 100644
--- a/src/Monolog/Formatter/WildfireFormatter.php
+++ b/src/Monolog/Formatter/WildfireFormatter.php
@@ -102,12 +102,12 @@ class WildfireFormatter extends NormalizerFormatter
throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter');
}
- protected function normalize($data)
+ protected function normalize($data, $depth = 0)
{
if (is_object($data) && !$data instanceof \DateTime) {
return $data;
}
- return parent::normalize($data);
+ return parent::normalize($data, $depth);
}
}
diff --git a/src/Monolog/Handler/AbstractHandler.php b/src/Monolog/Handler/AbstractHandler.php
index 758a425c..bf56549d 100644
--- a/src/Monolog/Handler/AbstractHandler.php
+++ b/src/Monolog/Handler/AbstractHandler.php
@@ -32,8 +32,8 @@ abstract class AbstractHandler implements HandlerInterface
protected $processors = array();
/**
- * @param int $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 int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($level = Logger::DEBUG, $bubble = true)
{
@@ -141,8 +141,8 @@ abstract class AbstractHandler implements HandlerInterface
/**
* Sets the bubbling behavior.
*
- * @param Boolean $bubble true means that this handler allows bubbling.
- * false means that bubbling is not permitted.
+ * @param bool $bubble true means that this handler allows bubbling.
+ * false means that bubbling is not permitted.
* @return self
*/
public function setBubble($bubble)
@@ -155,8 +155,8 @@ abstract class AbstractHandler implements HandlerInterface
/**
* Gets the bubbling behavior.
*
- * @return Boolean true means that this handler allows bubbling.
- * false means that bubbling is not permitted.
+ * @return bool true means that this handler allows bubbling.
+ * false means that bubbling is not permitted.
*/
public function getBubble()
{
diff --git a/src/Monolog/Handler/AbstractSyslogHandler.php b/src/Monolog/Handler/AbstractSyslogHandler.php
index e2b2832d..8c76aca0 100644
--- a/src/Monolog/Handler/AbstractSyslogHandler.php
+++ b/src/Monolog/Handler/AbstractSyslogHandler.php
@@ -53,9 +53,9 @@ abstract class AbstractSyslogHandler extends AbstractProcessingHandler
);
/**
- * @param mixed $facility
- * @param int $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 mixed $facility
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($facility = LOG_USER, $level = Logger::DEBUG, $bubble = true)
{
diff --git a/src/Monolog/Handler/BrowserConsoleHandler.php b/src/Monolog/Handler/BrowserConsoleHandler.php
index b3a21bd4..0225ee71 100644
--- a/src/Monolog/Handler/BrowserConsoleHandler.php
+++ b/src/Monolog/Handler/BrowserConsoleHandler.php
@@ -43,11 +43,11 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
protected function write(array $record)
{
// Accumulate records
- self::$records[] = $record;
+ static::$records[] = $record;
// Register shutdown handler if not already done
- if (!self::$initialized) {
- self::$initialized = true;
+ if (!static::$initialized) {
+ static::$initialized = true;
$this->registerShutdownFunction();
}
}
@@ -58,18 +58,18 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
*/
public static function send()
{
- $format = self::getResponseFormat();
+ $format = static::getResponseFormat();
if ($format === 'unknown') {
return;
}
- if (count(self::$records)) {
+ if (count(static::$records)) {
if ($format === 'html') {
- self::writeOutput('');
+ static::writeOutput('');
} elseif ($format === 'js') {
- self::writeOutput(self::generateScript());
+ static::writeOutput(static::generateScript());
}
- self::reset();
+ static::reset();
}
}
@@ -78,7 +78,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
*/
public static function reset()
{
- self::$records = array();
+ static::$records = array();
}
/**
@@ -133,18 +133,18 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
private static function generateScript()
{
$script = array();
- foreach (self::$records as $record) {
- $context = self::dump('Context', $record['context']);
- $extra = self::dump('Extra', $record['extra']);
+ foreach (static::$records as $record) {
+ $context = static::dump('Context', $record['context']);
+ $extra = static::dump('Extra', $record['extra']);
if (empty($context) && empty($extra)) {
- $script[] = self::call_array('log', self::handleStyles($record['formatted']));
+ $script[] = static::call_array('log', static::handleStyles($record['formatted']));
} else {
$script = array_merge($script,
- array(self::call_array('groupCollapsed', self::handleStyles($record['formatted']))),
+ array(static::call_array('groupCollapsed', static::handleStyles($record['formatted']))),
$context,
$extra,
- array(self::call('groupEnd'))
+ array(static::call('groupEnd'))
);
}
}
@@ -154,19 +154,19 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
private static function handleStyles($formatted)
{
- $args = array(self::quote('font-weight: normal'));
+ $args = array(static::quote('font-weight: normal'));
$format = '%c' . $formatted;
preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
foreach (array_reverse($matches) as $match) {
- $args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0]));
+ $args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0]));
$args[] = '"font-weight: normal"';
$pos = $match[0][1];
$format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0]));
}
- array_unshift($args, self::quote($format));
+ array_unshift($args, static::quote($format));
return $args;
}
@@ -198,13 +198,13 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
if (empty($dict)) {
return $script;
}
- $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title));
+ $script[] = static::call('log', static::quote('%c%s'), static::quote('font-weight: bold'), static::quote($title));
foreach ($dict as $key => $value) {
$value = json_encode($value);
if (empty($value)) {
- $value = self::quote('');
+ $value = static::quote('');
}
- $script[] = self::call('log', self::quote('%s: %o'), self::quote($key), $value);
+ $script[] = static::call('log', static::quote('%s: %o'), static::quote($key), $value);
}
return $script;
@@ -220,7 +220,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
$args = func_get_args();
$method = array_shift($args);
- return self::call_array($method, $args);
+ return static::call_array($method, $args);
}
private static function call_array($method, array $args)
diff --git a/src/Monolog/Handler/BufferHandler.php b/src/Monolog/Handler/BufferHandler.php
index 72f89535..c15e28a2 100644
--- a/src/Monolog/Handler/BufferHandler.php
+++ b/src/Monolog/Handler/BufferHandler.php
@@ -34,8 +34,8 @@ class BufferHandler extends AbstractHandler
* @param HandlerInterface $handler Handler.
* @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
* @param int $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 Boolean $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
*/
public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false)
{
diff --git a/src/Monolog/Handler/ChromePHPHandler.php b/src/Monolog/Handler/ChromePHPHandler.php
index 785cb0c9..37419a06 100644
--- a/src/Monolog/Handler/ChromePHPHandler.php
+++ b/src/Monolog/Handler/ChromePHPHandler.php
@@ -32,7 +32,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
* Header name
*/
const HEADER_NAME = 'X-ChromeLogger-Data';
-
+
/**
* Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+)
*/
@@ -45,7 +45,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
*
* Chrome limits the headers to 256KB, so when we sent 240KB we stop sending
*
- * @var Boolean
+ * @var bool
*/
protected static $overflowed = false;
@@ -58,8 +58,8 @@ class ChromePHPHandler extends AbstractProcessingHandler
protected static $sendHeaders = true;
/**
- * @param int $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 int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($level = Logger::DEBUG, $bubble = true)
{
@@ -174,7 +174,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
/**
* Verifies if the headers are accepted by the current user agent
*
- * @return Boolean
+ * @return bool
*/
protected function headersAccepted()
{
diff --git a/src/Monolog/Handler/DeduplicationHandler.php b/src/Monolog/Handler/DeduplicationHandler.php
index 7778c22a..35b55cb4 100644
--- a/src/Monolog/Handler/DeduplicationHandler.php
+++ b/src/Monolog/Handler/DeduplicationHandler.php
@@ -60,7 +60,7 @@ class DeduplicationHandler extends BufferHandler
* @param string $deduplicationStore The file/path where the deduplication log should be kept
* @param int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
* @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(HandlerInterface $handler, $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, $time = 60, $bubble = true)
{
diff --git a/src/Monolog/Handler/ElasticSearchHandler.php b/src/Monolog/Handler/ElasticSearchHandler.php
index 81967406..bb0f83eb 100644
--- a/src/Monolog/Handler/ElasticSearchHandler.php
+++ b/src/Monolog/Handler/ElasticSearchHandler.php
@@ -46,10 +46,10 @@ class ElasticSearchHandler extends AbstractProcessingHandler
protected $options = array();
/**
- * @param Client $client Elastica Client object
- * @param array $options Handler configuration
- * @param int $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 Client $client Elastica Client object
+ * @param array $options Handler configuration
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(Client $client, array $options = array(), $level = Logger::DEBUG, $bubble = true)
{
diff --git a/src/Monolog/Handler/ErrorLogHandler.php b/src/Monolog/Handler/ErrorLogHandler.php
index 1447a584..b2986b0f 100644
--- a/src/Monolog/Handler/ErrorLogHandler.php
+++ b/src/Monolog/Handler/ErrorLogHandler.php
@@ -28,10 +28,10 @@ class ErrorLogHandler extends AbstractProcessingHandler
protected $expandNewlines;
/**
- * @param int $messageType Says where the error should go.
- * @param int $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 Boolean $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
+ * @param int $messageType Says where the error should go.
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
*/
public function __construct($messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, $bubble = true, $expandNewlines = false)
{
diff --git a/src/Monolog/Handler/FilterHandler.php b/src/Monolog/Handler/FilterHandler.php
index 2a0f7fd1..938c1a7e 100644
--- a/src/Monolog/Handler/FilterHandler.php
+++ b/src/Monolog/Handler/FilterHandler.php
@@ -40,7 +40,7 @@ class FilterHandler extends AbstractHandler
/**
* Whether the messages that are handled can bubble up the stack or not
*
- * @var Boolean
+ * @var bool
*/
protected $bubble;
@@ -48,7 +48,7 @@ class FilterHandler extends AbstractHandler
* @param callable|HandlerInterface $handler Handler or factory callable($record, $this).
* @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
* @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, $bubble = true)
{
diff --git a/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php b/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php
index c3e42efe..aaca12cc 100644
--- a/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php
+++ b/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php
@@ -22,7 +22,7 @@ interface ActivationStrategyInterface
* Returns whether the given record activates the handler.
*
* @param array $record
- * @return Boolean
+ * @return bool
*/
public function isHandlerActivated(array $record);
}
diff --git a/src/Monolog/Handler/FingersCrossedHandler.php b/src/Monolog/Handler/FingersCrossedHandler.php
index d1dcaacf..d8026be6 100644
--- a/src/Monolog/Handler/FingersCrossedHandler.php
+++ b/src/Monolog/Handler/FingersCrossedHandler.php
@@ -41,8 +41,8 @@ class FingersCrossedHandler extends AbstractHandler
* @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler).
* @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action
* @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)
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true)
* @param int $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
*/
public function __construct($handler, $activationStrategy = null, $bufferSize = 0, $bubble = true, $stopBuffering = true, $passthruLevel = null)
diff --git a/src/Monolog/Handler/FirePHPHandler.php b/src/Monolog/Handler/FirePHPHandler.php
index fee47950..c30b1843 100644
--- a/src/Monolog/Handler/FirePHPHandler.php
+++ b/src/Monolog/Handler/FirePHPHandler.php
@@ -158,7 +158,7 @@ class FirePHPHandler extends AbstractProcessingHandler
/**
* Verifies if the headers are accepted by the current user agent
*
- * @return Boolean
+ * @return bool
*/
protected function headersAccepted()
{
diff --git a/src/Monolog/Handler/GelfHandler.php b/src/Monolog/Handler/GelfHandler.php
index d3847d82..71e46693 100644
--- a/src/Monolog/Handler/GelfHandler.php
+++ b/src/Monolog/Handler/GelfHandler.php
@@ -47,14 +47,6 @@ class GelfHandler extends AbstractProcessingHandler
$this->publisher = $publisher;
}
- /**
- * {@inheritdoc}
- */
- public function close()
- {
- $this->publisher = null;
- }
-
/**
* {@inheritdoc}
*/
diff --git a/src/Monolog/Handler/GroupHandler.php b/src/Monolog/Handler/GroupHandler.php
index 663f5a92..c38508c2 100644
--- a/src/Monolog/Handler/GroupHandler.php
+++ b/src/Monolog/Handler/GroupHandler.php
@@ -23,8 +23,8 @@ 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
+ * @param array $handlers Array of Handlers.
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(array $handlers, $bubble = true)
{
diff --git a/src/Monolog/Handler/HandlerInterface.php b/src/Monolog/Handler/HandlerInterface.php
index d920c4ba..8d5a4a09 100644
--- a/src/Monolog/Handler/HandlerInterface.php
+++ b/src/Monolog/Handler/HandlerInterface.php
@@ -31,7 +31,7 @@ interface HandlerInterface
*
* @param array $record Partial log record containing only a level key
*
- * @return Boolean
+ * @return bool
*/
public function isHandling(array $record);
@@ -46,7 +46,7 @@ interface HandlerInterface
* calling further handlers in the stack with a given log record.
*
* @param array $record The record to handle
- * @return Boolean true means that this handler handled the record, and that bubbling is not permitted.
+ * @return bool 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.
*/
public function handle(array $record);
diff --git a/src/Monolog/Handler/IFTTTHandler.php b/src/Monolog/Handler/IFTTTHandler.php
index d60a3c82..7f226220 100644
--- a/src/Monolog/Handler/IFTTTHandler.php
+++ b/src/Monolog/Handler/IFTTTHandler.php
@@ -30,10 +30,10 @@ class IFTTTHandler extends AbstractProcessingHandler
private $secretKey;
/**
- * @param string $eventName The name of the IFTTT Maker event that should be triggered
- * @param string $secretKey A valid IFTTT secret key
- * @param int $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 $eventName The name of the IFTTT Maker event that should be triggered
+ * @param string $secretKey A valid IFTTT secret key
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($eventName, $secretKey, $level = Logger::ERROR, $bubble = true)
{
diff --git a/src/Monolog/Handler/InsightOpsHandler.php b/src/Monolog/Handler/InsightOpsHandler.php
new file mode 100644
index 00000000..a12e3de5
--- /dev/null
+++ b/src/Monolog/Handler/InsightOpsHandler.php
@@ -0,0 +1,62 @@
+
+ *
+ * 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;
+
+/**
+ * Inspired on LogEntriesHandler.
+ *
+ * @author Robert Kaufmann III
+ * @author Gabriel Machado
+ */
+class InsightOpsHandler extends SocketHandler
+{
+ /**
+ * @var string
+ */
+ protected $logToken;
+
+ /**
+ * @param string $token Log token supplied by InsightOps
+ * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
+ * @param bool $useSSL Whether or not SSL encryption should be used
+ * @param int $level The minimum logging level to trigger this handler
+ * @param bool $bubble Whether or not messages that are handled should bubble up the stack.
+ *
+ * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
+ */
+ public function __construct($token, $region = 'us', $useSSL = true, $level = Logger::DEBUG, $bubble = true)
+ {
+ if ($useSSL && !extension_loaded('openssl')) {
+ throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler');
+ }
+
+ $endpoint = $useSSL
+ ? 'ssl://' . $region . '.data.logs.insight.rapid7.com:443'
+ : $region . '.data.logs.insight.rapid7.com:80';
+
+ parent::__construct($endpoint, $level, $bubble);
+ $this->logToken = $token;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param array $record
+ * @return string
+ */
+ protected function generateDataStream($record)
+ {
+ return $this->logToken . ' ' . $record['formatted'];
+ }
+}
diff --git a/src/Monolog/Handler/MandrillHandler.php b/src/Monolog/Handler/MandrillHandler.php
index ab95924f..3f0956a9 100644
--- a/src/Monolog/Handler/MandrillHandler.php
+++ b/src/Monolog/Handler/MandrillHandler.php
@@ -27,7 +27,7 @@ class MandrillHandler extends MailHandler
* @param string $apiKey A valid Mandrill API key
* @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
* @param int $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 bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($apiKey, $message, $level = Logger::ERROR, $bubble = true)
{
diff --git a/src/Monolog/Handler/NewRelicHandler.php b/src/Monolog/Handler/NewRelicHandler.php
index 6718e9e0..ed2efa27 100644
--- a/src/Monolog/Handler/NewRelicHandler.php
+++ b/src/Monolog/Handler/NewRelicHandler.php
@@ -84,7 +84,7 @@ class NewRelicHandler extends AbstractProcessingHandler
unset($record['formatted']['context']['transaction_name']);
}
- if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) {
+ if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
newrelic_notice_error($record['message'], $record['context']['exception']);
unset($record['formatted']['context']['exception']);
} else {
diff --git a/src/Monolog/Handler/PsrHandler.php b/src/Monolog/Handler/PsrHandler.php
index 1ae85845..a99e6ab7 100644
--- a/src/Monolog/Handler/PsrHandler.php
+++ b/src/Monolog/Handler/PsrHandler.php
@@ -31,7 +31,7 @@ class PsrHandler extends AbstractHandler
/**
* @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied
* @param int $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 bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, $bubble = true)
{
diff --git a/src/Monolog/Handler/PushoverHandler.php b/src/Monolog/Handler/PushoverHandler.php
index bba72005..f27bb3da 100644
--- a/src/Monolog/Handler/PushoverHandler.php
+++ b/src/Monolog/Handler/PushoverHandler.php
@@ -69,8 +69,8 @@ class PushoverHandler extends SocketHandler
* @param string|array $users Pushover user id or array of ids the message will be sent to
* @param string $title Title sent to the Pushover API
* @param int $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 Boolean $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
* the pushover.net app owner. OpenSSL is required for this option.
* @param int $highPriorityLevel The minimum logging level at which this handler will start
* sending "high priority" requests to the Pushover API
@@ -180,6 +180,6 @@ class PushoverHandler extends SocketHandler
*/
public function useFormattedMessage($value)
{
- $this->useFormattedMessage = (boolean) $value;
+ $this->useFormattedMessage = (bool) $value;
}
}
diff --git a/src/Monolog/Handler/RavenHandler.php b/src/Monolog/Handler/RavenHandler.php
index 53a8b391..34ff0091 100644
--- a/src/Monolog/Handler/RavenHandler.php
+++ b/src/Monolog/Handler/RavenHandler.php
@@ -57,7 +57,7 @@ class RavenHandler extends AbstractProcessingHandler
/**
* @param Raven_Client $ravenClient
* @param int $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 bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true)
{
@@ -180,7 +180,7 @@ class RavenHandler extends AbstractProcessingHandler
}
if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
- $options['extra']['message'] = $record['formatted'];
+ $options['message'] = $record['formatted'];
$this->ravenClient->captureException($record['context']['exception'], $options);
} else {
$this->ravenClient->captureMessage($record['formatted'], array(), $options);
diff --git a/src/Monolog/Handler/RotatingFileHandler.php b/src/Monolog/Handler/RotatingFileHandler.php
index 3b60b3d1..cc9fd4d3 100644
--- a/src/Monolog/Handler/RotatingFileHandler.php
+++ b/src/Monolog/Handler/RotatingFileHandler.php
@@ -39,9 +39,9 @@ class RotatingFileHandler extends StreamHandler
* @param string $filename
* @param int $maxFiles The maximal amount of files to keep (0 means unlimited)
* @param int $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 bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
- * @param Boolean $useLocking Try to lock log file before doing any writes
+ * @param bool $useLocking Try to lock log file before doing any writes
*/
public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false)
{
@@ -166,7 +166,7 @@ class RotatingFileHandler extends StreamHandler
$fileInfo = pathinfo($this->filename);
$glob = str_replace(
array('{filename}', '{date}'),
- array($fileInfo['filename'], '*'),
+ array($fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'),
$fileInfo['dirname'] . '/' . $this->filenameFormat
);
if (!empty($fileInfo['extension'])) {
diff --git a/src/Monolog/Handler/Slack/SlackRecord.php b/src/Monolog/Handler/Slack/SlackRecord.php
old mode 100644
new mode 100755
index 38bc838a..e55e0e2e
--- a/src/Monolog/Handler/Slack/SlackRecord.php
+++ b/src/Monolog/Handler/Slack/SlackRecord.php
@@ -146,7 +146,7 @@ class SlackRecord
if ($this->useShortAttachment) {
$attachment['fields'][] = $this->generateAttachmentField(
- ucfirst($key),
+ $key,
$record[$key]
);
} else {
@@ -229,8 +229,8 @@ class SlackRecord
/**
* Generates attachment field
*
- * @param string $title
- * @param string|array $value\
+ * @param string $title
+ * @param string|array $value
*
* @return array
*/
@@ -241,7 +241,7 @@ class SlackRecord
: $value;
return array(
- 'title' => $title,
+ 'title' => ucfirst($title),
'value' => $value,
'short' => false
);
@@ -257,7 +257,7 @@ class SlackRecord
private function generateAttachmentFields(array $data)
{
$fields = array();
- foreach ($data as $key => $value) {
+ foreach ($this->normalizerFormatter->format($data) as $key => $value) {
$fields[] = $this->generateAttachmentField($key, $value);
}
diff --git a/src/Monolog/Handler/SlackHandler.php b/src/Monolog/Handler/SlackHandler.php
index 3ac4d836..45d634f4 100644
--- a/src/Monolog/Handler/SlackHandler.php
+++ b/src/Monolog/Handler/SlackHandler.php
@@ -75,6 +75,11 @@ class SlackHandler extends SocketHandler
return $this->slackRecord;
}
+ public function getToken()
+ {
+ return $this->token;
+ }
+
/**
* {@inheritdoc}
*
diff --git a/src/Monolog/Handler/SlackWebhookHandler.php b/src/Monolog/Handler/SlackWebhookHandler.php
index 9a1bbb44..1ef85fae 100644
--- a/src/Monolog/Handler/SlackWebhookHandler.php
+++ b/src/Monolog/Handler/SlackWebhookHandler.php
@@ -70,6 +70,11 @@ class SlackWebhookHandler extends AbstractProcessingHandler
return $this->slackRecord;
}
+ public function getWebhookUrl()
+ {
+ return $this->webhookUrl;
+ }
+
/**
* {@inheritdoc}
*
diff --git a/src/Monolog/Handler/SocketHandler.php b/src/Monolog/Handler/SocketHandler.php
index 7a61bf4e..db50d97f 100644
--- a/src/Monolog/Handler/SocketHandler.php
+++ b/src/Monolog/Handler/SocketHandler.php
@@ -27,15 +27,16 @@ class SocketHandler extends AbstractProcessingHandler
private $timeout = 0;
private $writingTimeout = 10;
private $lastSentBytes = null;
+ private $chunkSize = null;
private $persistent = false;
private $errno;
private $errstr;
private $lastWritingAt;
/**
- * @param string $connectionString Socket connection string
- * @param int $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 int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true)
{
@@ -87,7 +88,7 @@ class SocketHandler extends AbstractProcessingHandler
*/
public function setPersistent($persistent)
{
- $this->persistent = (boolean) $persistent;
+ $this->persistent = (bool) $persistent;
}
/**
@@ -127,6 +128,16 @@ class SocketHandler extends AbstractProcessingHandler
$this->writingTimeout = (float) $seconds;
}
+ /**
+ * Set chunk size. Only has effect during connection in the writing cycle.
+ *
+ * @param float $bytes
+ */
+ public function setChunkSize($bytes)
+ {
+ $this->chunkSize = $bytes;
+ }
+
/**
* Get current connection string
*
@@ -177,6 +188,16 @@ class SocketHandler extends AbstractProcessingHandler
return $this->writingTimeout;
}
+ /**
+ * Get current chunk size
+ *
+ * @return float
+ */
+ public function getChunkSize()
+ {
+ return $this->chunkSize;
+ }
+
/**
* Check to see if the socket is currently available.
*
@@ -219,6 +240,16 @@ class SocketHandler extends AbstractProcessingHandler
return stream_set_timeout($this->resource, $seconds, $microseconds);
}
+ /**
+ * Wrapper to allow mocking
+ *
+ * @see http://php.net/manual/en/function.stream-set-chunk-size.php
+ */
+ protected function streamSetChunkSize()
+ {
+ return stream_set_chunk_size($this->resource, $this->chunkSize);
+ }
+
/**
* Wrapper to allow mocking
*/
@@ -268,6 +299,7 @@ class SocketHandler extends AbstractProcessingHandler
{
$this->createSocketResource();
$this->setSocketTimeout();
+ $this->setStreamChunkSize();
}
private function createSocketResource()
@@ -290,6 +322,13 @@ class SocketHandler extends AbstractProcessingHandler
}
}
+ private function setStreamChunkSize()
+ {
+ if ($this->chunkSize && !$this->streamSetChunkSize()) {
+ throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()");
+ }
+ }
+
private function writeToSocket($data)
{
$length = strlen($data);
diff --git a/src/Monolog/Handler/StreamHandler.php b/src/Monolog/Handler/StreamHandler.php
index 09a15738..a35b7e4c 100644
--- a/src/Monolog/Handler/StreamHandler.php
+++ b/src/Monolog/Handler/StreamHandler.php
@@ -32,9 +32,9 @@ class StreamHandler extends AbstractProcessingHandler
/**
* @param resource|string $stream
* @param int $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 bool $bubble Whether the messages that are handled can bubble up the stack or not
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
- * @param Boolean $useLocking Try to lock log file before doing any writes
+ * @param bool $useLocking Try to lock log file before doing any writes
*
* @throws \Exception If a missing directory is not buildable
* @throws \InvalidArgumentException If stream is not a resource or string
@@ -167,7 +167,7 @@ class StreamHandler extends AbstractProcessingHandler
set_error_handler(array($this, 'customErrorHandler'));
$status = mkdir($dir, 0777, true);
restore_error_handler();
- if (false === $status) {
+ if (false === $status && !is_dir($dir)) {
throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and its not buildable: '.$this->errorMessage, $dir));
}
}
diff --git a/src/Monolog/Handler/SwiftMailerHandler.php b/src/Monolog/Handler/SwiftMailerHandler.php
index 72f44a53..ac7b16ff 100644
--- a/src/Monolog/Handler/SwiftMailerHandler.php
+++ b/src/Monolog/Handler/SwiftMailerHandler.php
@@ -12,6 +12,7 @@
namespace Monolog\Handler;
use Monolog\Logger;
+use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Swift;
@@ -29,7 +30,7 @@ class SwiftMailerHandler extends MailHandler
* @param \Swift_Mailer $mailer The mailer to use
* @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
* @param int $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 bool $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)
{
@@ -47,6 +48,17 @@ class SwiftMailerHandler extends MailHandler
$this->mailer->send($this->buildMessage($content, $records));
}
+ /**
+ * Gets the formatter for the Swift_Message subject.
+ *
+ * @param string $format The format of the subject
+ * @return FormatterInterface
+ */
+ protected function getSubjectFormatter($format)
+ {
+ return new LineFormatter($format);
+ }
+
/**
* Creates instance of Swift_Message to be sent
*
@@ -69,7 +81,7 @@ class SwiftMailerHandler extends MailHandler
}
if ($records) {
- $subjectFormatter = new LineFormatter($message->getSubject());
+ $subjectFormatter = $this->getSubjectFormatter($message->getSubject());
$message->setSubject($subjectFormatter->format($this->getHighestRecord($records)));
}
diff --git a/src/Monolog/Handler/SyslogHandler.php b/src/Monolog/Handler/SyslogHandler.php
index 376bc3b2..f770c802 100644
--- a/src/Monolog/Handler/SyslogHandler.php
+++ b/src/Monolog/Handler/SyslogHandler.php
@@ -32,11 +32,11 @@ class SyslogHandler extends AbstractSyslogHandler
protected $logopts;
/**
- * @param string $ident
- * @param mixed $facility
- * @param int $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 int $logopts Option flags for the openlog() call, defaults to LOG_PID
+ * @param string $ident
+ * @param mixed $facility
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
*/
public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $logopts = LOG_PID)
{
diff --git a/src/Monolog/Handler/SyslogUdpHandler.php b/src/Monolog/Handler/SyslogUdpHandler.php
index 4718711b..e14b378c 100644
--- a/src/Monolog/Handler/SyslogUdpHandler.php
+++ b/src/Monolog/Handler/SyslogUdpHandler.php
@@ -25,12 +25,12 @@ class SyslogUdpHandler extends AbstractSyslogHandler
protected $ident;
/**
- * @param string $host
- * @param int $port
- * @param mixed $facility
- * @param int $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 $ident Program name or tag for each log message.
+ * @param string $host
+ * @param int $port
+ * @param mixed $facility
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param string $ident Program name or tag for each log message.
*/
public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $ident = 'php')
{
diff --git a/src/Monolog/Handler/WhatFailureGroupHandler.php b/src/Monolog/Handler/WhatFailureGroupHandler.php
index 2732ba3d..6bc4671c 100644
--- a/src/Monolog/Handler/WhatFailureGroupHandler.php
+++ b/src/Monolog/Handler/WhatFailureGroupHandler.php
@@ -48,6 +48,16 @@ class WhatFailureGroupHandler extends GroupHandler
*/
public function handleBatch(array $records)
{
+ if ($this->processors) {
+ $processed = array();
+ foreach ($records as $record) {
+ foreach ($this->processors as $processor) {
+ $processed[] = call_user_func($processor, $record);
+ }
+ }
+ $records = $processed;
+ }
+
foreach ($this->handlers as $handler) {
try {
$handler->handleBatch($records);
diff --git a/src/Monolog/Logger.php b/src/Monolog/Logger.php
index 49d00af1..5034ead1 100644
--- a/src/Monolog/Logger.php
+++ b/src/Monolog/Logger.php
@@ -15,6 +15,7 @@ use Monolog\Handler\HandlerInterface;
use Monolog\Handler\StreamHandler;
use Psr\Log\LoggerInterface;
use Psr\Log\InvalidArgumentException;
+use Exception;
/**
* Monolog log channel
@@ -133,6 +134,11 @@ class Logger implements LoggerInterface
*/
protected $microsecondTimestamps = true;
+ /**
+ * @var callable
+ */
+ protected $exceptionHandler;
+
/**
* @param string $name The logging channel
* @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
@@ -141,7 +147,7 @@ class Logger implements LoggerInterface
public function __construct($name, array $handlers = array(), array $processors = array())
{
$this->name = $name;
- $this->handlers = $handlers;
+ $this->setHandlers($handlers);
$this->processors = $processors;
}
@@ -281,7 +287,7 @@ class Logger implements LoggerInterface
* @param int $level The logging level
* @param string $message The log message
* @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @return bool Whether the record has been processed
*/
public function addRecord($level, $message, array $context = array())
{
@@ -329,16 +335,20 @@ class Logger implements LoggerInterface
'extra' => array(),
);
- foreach ($this->processors as $processor) {
- $record = call_user_func($processor, $record);
- }
-
- while ($handler = current($this->handlers)) {
- if (true === $handler->handle($record)) {
- break;
+ try {
+ foreach ($this->processors as $processor) {
+ $record = call_user_func($processor, $record);
}
- next($this->handlers);
+ while ($handler = current($this->handlers)) {
+ if (true === $handler->handle($record)) {
+ break;
+ }
+
+ next($this->handlers);
+ }
+ } catch (Exception $e) {
+ $this->handleException($e, $record);
}
return true;
@@ -347,9 +357,9 @@ class Logger implements LoggerInterface
/**
* 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
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function addDebug($message, array $context = array())
{
@@ -359,9 +369,9 @@ class Logger implements LoggerInterface
/**
* 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
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function addInfo($message, array $context = array())
{
@@ -371,9 +381,9 @@ class Logger implements LoggerInterface
/**
* Adds a log record at the NOTICE level.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function addNotice($message, array $context = array())
{
@@ -383,9 +393,9 @@ class Logger implements LoggerInterface
/**
* 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
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function addWarning($message, array $context = array())
{
@@ -395,9 +405,9 @@ class Logger implements LoggerInterface
/**
* 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
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function addError($message, array $context = array())
{
@@ -407,9 +417,9 @@ class Logger implements LoggerInterface
/**
* 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
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function addCritical($message, array $context = array())
{
@@ -419,9 +429,9 @@ class Logger implements LoggerInterface
/**
* 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
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function addAlert($message, array $context = array())
{
@@ -431,9 +441,9 @@ class Logger implements LoggerInterface
/**
* Adds a log record at the EMERGENCY level.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function addEmergency($message, array $context = array())
{
@@ -484,7 +494,7 @@ class Logger implements LoggerInterface
* Checks whether the Logger has a handler that listens on the given level
*
* @param int $level
- * @return Boolean
+ * @return bool
*/
public function isHandling($level)
{
@@ -501,15 +511,52 @@ class Logger implements LoggerInterface
return false;
}
+ /**
+ * Set a custom exception handler
+ *
+ * @param callable $callback
+ * @return $this
+ */
+ public function setExceptionHandler($callback)
+ {
+ if (!is_callable($callback)) {
+ throw new \InvalidArgumentException('Exception handler must be valid callable (callback or object with an __invoke method), '.var_export($callback, true).' given');
+ }
+ $this->exceptionHandler = $callback;
+
+ return $this;
+ }
+
+ /**
+ * @return callable
+ */
+ public function getExceptionHandler()
+ {
+ return $this->exceptionHandler;
+ }
+
+ /**
+ * Delegates exception management to the custom exception handler,
+ * or throws the exception if no custom handler is set.
+ */
+ protected function handleException(Exception $e, array $record)
+ {
+ if (!$this->exceptionHandler) {
+ throw $e;
+ }
+
+ call_user_func($this->exceptionHandler, $e, $record);
+ }
+
/**
* Adds a log record at an arbitrary level.
*
* This method allows for compatibility with common interfaces.
*
* @param mixed $level The log level
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function log($level, $message, array $context = array())
{
@@ -523,9 +570,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function debug($message, array $context = array())
{
@@ -537,9 +584,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function info($message, array $context = array())
{
@@ -551,9 +598,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function notice($message, array $context = array())
{
@@ -565,9 +612,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function warn($message, array $context = array())
{
@@ -579,9 +626,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function warning($message, array $context = array())
{
@@ -593,9 +640,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function err($message, array $context = array())
{
@@ -607,9 +654,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function error($message, array $context = array())
{
@@ -621,9 +668,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function crit($message, array $context = array())
{
@@ -635,9 +682,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function critical($message, array $context = array())
{
@@ -649,9 +696,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function alert($message, array $context = array())
{
@@ -663,9 +710,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function emerg($message, array $context = array())
{
@@ -677,9 +724,9 @@ class Logger implements LoggerInterface
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return Boolean Whether the record has been processed
+ * @param string $message The log message
+ * @param array $context The log context
+ * @return bool Whether the record has been processed
*/
public function emergency($message, array $context = array())
{
diff --git a/src/Monolog/Processor/MemoryProcessor.php b/src/Monolog/Processor/MemoryProcessor.php
index 85f9dc5e..73f132d7 100644
--- a/src/Monolog/Processor/MemoryProcessor.php
+++ b/src/Monolog/Processor/MemoryProcessor.php
@@ -34,8 +34,8 @@ abstract class MemoryProcessor
*/
public function __construct($realUsage = true, $useFormatting = true)
{
- $this->realUsage = (boolean) $realUsage;
- $this->useFormatting = (boolean) $useFormatting;
+ $this->realUsage = (bool) $realUsage;
+ $this->useFormatting = (bool) $useFormatting;
}
/**
diff --git a/tests/Monolog/Formatter/FluentdFormatterTest.php b/tests/Monolog/Formatter/FluentdFormatterTest.php
index 622b2bae..fd36dbcf 100644
--- a/tests/Monolog/Formatter/FluentdFormatterTest.php
+++ b/tests/Monolog/Formatter/FluentdFormatterTest.php
@@ -40,7 +40,7 @@ class FluentdFormatterTest extends TestCase
$formatter = new FluentdFormatter();
$this->assertEquals(
- '["test",0,{"message":"test","extra":[],"level":300,"level_name":"WARNING"}]',
+ '["test",0,{"message":"test","context":[],"extra":[],"level":300,"level_name":"WARNING"}]',
$formatter->format($record)
);
}
@@ -55,7 +55,7 @@ class FluentdFormatterTest extends TestCase
$formatter = new FluentdFormatter(true);
$this->assertEquals(
- '["test.error",0,{"message":"test","extra":[]}]',
+ '["test.error",0,{"message":"test","context":[],"extra":[]}]',
$formatter->format($record)
);
}
diff --git a/tests/Monolog/Formatter/JsonFormatterTest.php b/tests/Monolog/Formatter/JsonFormatterTest.php
index c9445f36..24b06cc9 100644
--- a/tests/Monolog/Formatter/JsonFormatterTest.php
+++ b/tests/Monolog/Formatter/JsonFormatterTest.php
@@ -180,4 +180,40 @@ class JsonFormatterTest extends TestCase
'}';
return $formattedException;
}
+
+ public function testNormalizeHandleLargeArraysWithExactly1000Items()
+ {
+ $formatter = new NormalizerFormatter();
+ $largeArray = range(1, 1000);
+
+ $res = $formatter->format(array(
+ 'level_name' => 'CRITICAL',
+ 'channel' => 'test',
+ 'message' => 'bar',
+ 'context' => array($largeArray),
+ 'datetime' => new \DateTime,
+ 'extra' => array(),
+ ));
+
+ $this->assertCount(1000, $res['context'][0]);
+ $this->assertArrayNotHasKey('...', $res['context'][0]);
+ }
+
+ public function testNormalizeHandleLargeArrays()
+ {
+ $formatter = new NormalizerFormatter();
+ $largeArray = range(1, 2000);
+
+ $res = $formatter->format(array(
+ 'level_name' => 'CRITICAL',
+ 'channel' => 'test',
+ 'message' => 'bar',
+ 'context' => array($largeArray),
+ 'datetime' => new \DateTime,
+ 'extra' => array(),
+ ));
+
+ $this->assertCount(1001, $res['context'][0]);
+ $this->assertEquals('Over 1000 items (2000 total), aborting normalization', $res['context'][0]['...']);
+ }
}
diff --git a/tests/Monolog/Formatter/NormalizerFormatterTest.php b/tests/Monolog/Formatter/NormalizerFormatterTest.php
index 57bcdf98..b4f82897 100644
--- a/tests/Monolog/Formatter/NormalizerFormatterTest.php
+++ b/tests/Monolog/Formatter/NormalizerFormatterTest.php
@@ -193,6 +193,15 @@ class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(@json_encode(array($foo, $bar)), $res);
}
+ public function testCanNormalizeReferences()
+ {
+ $formatter = new NormalizerFormatter();
+ $x = array('foo' => 'bar');
+ $y = array('x' => &$x);
+ $x['y'] = &$y;
+ $formatter->format($y);
+ }
+
public function testIgnoresInvalidTypes()
{
// set up the recursion
@@ -217,6 +226,24 @@ class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(@json_encode(array($resource)), $res);
}
+ public function testNormalizeHandleLargeArraysWithExactly1000Items()
+ {
+ $formatter = new NormalizerFormatter();
+ $largeArray = range(1, 1000);
+
+ $res = $formatter->format(array(
+ 'level_name' => 'CRITICAL',
+ 'channel' => 'test',
+ 'message' => 'bar',
+ 'context' => array($largeArray),
+ 'datetime' => new \DateTime,
+ 'extra' => array(),
+ ));
+
+ $this->assertCount(1000, $res['context'][0]);
+ $this->assertArrayNotHasKey('...', $res['context'][0]);
+ }
+
public function testNormalizeHandleLargeArrays()
{
$formatter = new NormalizerFormatter();
@@ -231,7 +258,7 @@ class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase
'extra' => array(),
));
- $this->assertCount(1000, $res['context'][0]);
+ $this->assertCount(1001, $res['context'][0]);
$this->assertEquals('Over 1000 items (2000 total), aborting normalization', $res['context'][0]['...']);
}
diff --git a/tests/Monolog/Handler/InsightOpsHandlerTest.php b/tests/Monolog/Handler/InsightOpsHandlerTest.php
new file mode 100644
index 00000000..97c18b59
--- /dev/null
+++ b/tests/Monolog/Handler/InsightOpsHandlerTest.php
@@ -0,0 +1,80 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+ namespace Monolog\Handler;
+
+ use Monolog\TestCase;
+ use Monolog\Logger;
+
+/**
+ * @author Robert Kaufmann III
+ * @author Gabriel Machado
+ */
+class InsightOpsHandlerTest extends TestCase
+{
+ /**
+ * @var resource
+ */
+ private $resource;
+
+ /**
+ * @var LogEntriesHandler
+ */
+ private $handler;
+
+ public function testWriteContent()
+ {
+ $this->createHandler();
+ $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test'));
+
+ fseek($this->resource, 0);
+ $content = fread($this->resource, 1024);
+
+ $this->assertRegexp('/testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] test.CRITICAL: Critical write test/', $content);
+ }
+
+ public function testWriteBatchContent()
+ {
+ $this->createHandler();
+ $this->handler->handleBatch($this->getMultipleRecords());
+
+ fseek($this->resource, 0);
+ $content = fread($this->resource, 1024);
+
+ $this->assertRegexp('/(testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] .* \[\] \[\]\n){3}/', $content);
+ }
+
+ private function createHandler()
+ {
+ $useSSL = extension_loaded('openssl');
+ $args = array('testToken', 'us', $useSSL, Logger::DEBUG, true);
+ $this->resource = fopen('php://memory', 'a');
+ $this->handler = $this->getMock(
+ '\Monolog\Handler\InsightOpsHandler',
+ array('fsockopen', 'streamSetTimeout', 'closeSocket'),
+ $args
+ );
+
+ $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
+ $reflectionProperty->setAccessible(true);
+ $reflectionProperty->setValue($this->handler, 'localhost:1234');
+
+ $this->handler->expects($this->any())
+ ->method('fsockopen')
+ ->will($this->returnValue($this->resource));
+ $this->handler->expects($this->any())
+ ->method('streamSetTimeout')
+ ->will($this->returnValue(true));
+ $this->handler->expects($this->any())
+ ->method('closeSocket')
+ ->will($this->returnValue(true));
+ }
+}
diff --git a/tests/Monolog/Handler/RotatingFileHandlerTest.php b/tests/Monolog/Handler/RotatingFileHandlerTest.php
index f1feb228..c6f5fac9 100644
--- a/tests/Monolog/Handler/RotatingFileHandlerTest.php
+++ b/tests/Monolog/Handler/RotatingFileHandlerTest.php
@@ -191,6 +191,40 @@ class RotatingFileHandlerTest extends TestCase
);
}
+ /**
+ * @dataProvider rotationWhenSimilarFilesExistTests
+ */
+ public function testRotationWhenSimilarFileNamesExist($dateFormat)
+ {
+ touch($old1 = __DIR__.'/Fixtures/foo-foo-'.date($dateFormat).'.rot');
+ touch($old2 = __DIR__.'/Fixtures/foo-bar-'.date($dateFormat).'.rot');
+
+ $log = __DIR__.'/Fixtures/foo-'.date($dateFormat).'.rot';
+
+ $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2);
+ $handler->setFormatter($this->getIdentityFormatter());
+ $handler->setFilenameFormat('{filename}-{date}', $dateFormat);
+ $handler->handle($this->getRecord());
+ $handler->close();
+
+ $this->assertTrue(file_exists($log));
+ }
+
+ public function rotationWhenSimilarFilesExistTests()
+ {
+
+ return array(
+ 'Rotation is triggered when the file of the current day is not present but similar exists'
+ => array(RotatingFileHandler::FILE_PER_DAY),
+
+ 'Rotation is triggered when the file of the current month is not present but similar exists'
+ => array(RotatingFileHandler::FILE_PER_MONTH),
+
+ 'Rotation is triggered when the file of the current year is not present but similar exists'
+ => array(RotatingFileHandler::FILE_PER_YEAR),
+ );
+ }
+
public function testReuseCurrentFile()
{
$log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot';
diff --git a/tests/Monolog/Handler/Slack/SlackRecordTest.php b/tests/Monolog/Handler/Slack/SlackRecordTest.php
index e1aa96d7..b9de7367 100644
--- a/tests/Monolog/Handler/Slack/SlackRecordTest.php
+++ b/tests/Monolog/Handler/Slack/SlackRecordTest.php
@@ -320,12 +320,12 @@ class SlackRecordTest extends TestCase
'short' => false,
),
array(
- 'title' => 'tags',
+ 'title' => 'Tags',
'value' => sprintf('```%s```', json_encode($extra['tags'])),
'short' => false
),
array(
- 'title' => 'test',
+ 'title' => 'Test',
'value' => $context['test'],
'short' => false
)
@@ -353,6 +353,14 @@ class SlackRecordTest extends TestCase
$this->assertSame($record['datetime']->getTimestamp(), $attachment['ts']);
}
+ public function testContextHasException()
+ {
+ $record = $this->getRecord(Logger::CRITICAL, 'This is a critical message.', array('exception' => new \Exception()));
+ $slackRecord = new SlackRecord(null, null, true, null, false, true);
+ $data = $slackRecord->getSlackData($record);
+ $this->assertInternalType('string', $data['attachments'][0]['fields'][1]['value']);
+ }
+
public function testExcludeExtraAndContextFields()
{
$record = $this->getRecord(
@@ -368,12 +376,12 @@ class SlackRecordTest extends TestCase
$expected = array(
array(
- 'title' => 'info',
+ 'title' => 'Info',
'value' => sprintf('```%s```', json_encode(array('author' => 'Jordi'), $this->jsonPrettyPrintFlag)),
'short' => false
),
array(
- 'title' => 'tags',
+ 'title' => 'Tags',
'value' => sprintf('```%s```', json_encode(array('web'))),
'short' => false
),
diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php
index 1f9c1f28..1da987c9 100644
--- a/tests/Monolog/Handler/SocketHandlerTest.php
+++ b/tests/Monolog/Handler/SocketHandlerTest.php
@@ -77,6 +77,13 @@ class SocketHandlerTest extends TestCase
$this->assertEquals(10.25, $this->handler->getWritingTimeout());
}
+ public function testSetChunkSize()
+ {
+ $this->createHandler('localhost:1234');
+ $this->handler->setChunkSize(1025);
+ $this->assertEquals(1025, $this->handler->getChunkSize());
+ }
+
public function testSetConnectionString()
{
$this->createHandler('tcp://localhost:9090');
@@ -120,6 +127,19 @@ class SocketHandlerTest extends TestCase
$this->writeRecord('Hello world');
}
+ /**
+ * @expectedException UnexpectedValueException
+ */
+ public function testExceptionIsThrownIfCannotSetChunkSize()
+ {
+ $this->setMockHandler(array('streamSetChunkSize'));
+ $this->handler->setChunkSize(8192);
+ $this->handler->expects($this->once())
+ ->method('streamSetChunkSize')
+ ->will($this->returnValue(false));
+ $this->writeRecord('Hello world');
+ }
+
/**
* @expectedException RuntimeException
*/
@@ -304,6 +324,12 @@ class SocketHandlerTest extends TestCase
->will($this->returnValue(true));
}
+ if (!in_array('streamSetChunkSize', $methods)) {
+ $this->handler->expects($this->any())
+ ->method('streamSetChunkSize')
+ ->will($this->returnValue(8192));
+ }
+
$this->handler->setFormatter($this->getIdentityFormatter());
}
}
diff --git a/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php b/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php
index 8d37a1fc..0594a232 100644
--- a/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php
+++ b/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php
@@ -87,6 +87,29 @@ class WhatFailureGroupHandlerTest extends TestCase
$this->assertTrue($records[0]['extra']['foo']);
}
+ /**
+ * @covers Monolog\Handler\WhatFailureGroupHandler::handleBatch
+ */
+ public function testHandleBatchUsesProcessors()
+ {
+ $testHandlers = array(new TestHandler(), new TestHandler());
+ $handler = new WhatFailureGroupHandler($testHandlers);
+ $handler->pushProcessor(function ($record) {
+ $record['extra']['foo'] = true;
+
+ return $record;
+ });
+ $handler->handleBatch(array($this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO)));
+ foreach ($testHandlers as $test) {
+ $this->assertTrue($test->hasDebugRecords());
+ $this->assertTrue($test->hasInfoRecords());
+ $this->assertTrue(count($test->getRecords()) === 2);
+ $records = $test->getRecords();
+ $this->assertTrue($records[0]['extra']['foo']);
+ $this->assertTrue($records[1]['extra']['foo']);
+ }
+ }
+
/**
* @covers Monolog\Handler\WhatFailureGroupHandler::handle
*/
diff --git a/tests/Monolog/LoggerTest.php b/tests/Monolog/LoggerTest.php
index 1ecc34a0..f938ea02 100644
--- a/tests/Monolog/LoggerTest.php
+++ b/tests/Monolog/LoggerTest.php
@@ -545,4 +545,73 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
'without microseconds' => array(false, PHP_VERSION_ID >= 70100 ? 'assertNotSame' : 'assertSame'),
);
}
+
+ /**
+ * @covers Monolog\Logger::setExceptionHandler
+ */
+ public function testSetExceptionHandler()
+ {
+ $logger = new Logger(__METHOD__);
+ $this->assertNull($logger->getExceptionHandler());
+ $callback = function ($ex) {
+ };
+ $logger->setExceptionHandler($callback);
+ $this->assertEquals($callback, $logger->getExceptionHandler());
+ }
+
+ /**
+ * @covers Monolog\Logger::setExceptionHandler
+ * @expectedException InvalidArgumentException
+ */
+ public function testBadExceptionHandlerType()
+ {
+ $logger = new Logger(__METHOD__);
+ $logger->setExceptionHandler(false);
+ }
+
+ /**
+ * @covers Monolog\Logger::handleException
+ * @expectedException Exception
+ */
+ public function testDefaultHandleException()
+ {
+ $logger = new Logger(__METHOD__);
+ $handler = $this->getMock('Monolog\Handler\HandlerInterface');
+ $handler->expects($this->any())
+ ->method('isHandling')
+ ->will($this->returnValue(true))
+ ;
+ $handler->expects($this->any())
+ ->method('handle')
+ ->will($this->throwException(new \Exception('Some handler exception')))
+ ;
+ $logger->pushHandler($handler);
+ $logger->info('test');
+ }
+
+ /**
+ * @covers Monolog\Logger::handleException
+ * @covers Monolog\Logger::addRecord
+ */
+ public function testCustomHandleException()
+ {
+ $logger = new Logger(__METHOD__);
+ $that = $this;
+ $logger->setExceptionHandler(function ($e, $record) use ($that) {
+ $that->assertEquals($e->getMessage(), 'Some handler exception');
+ $that->assertTrue(is_array($record));
+ $that->assertEquals($record['message'], 'test');
+ });
+ $handler = $this->getMock('Monolog\Handler\HandlerInterface');
+ $handler->expects($this->any())
+ ->method('isHandling')
+ ->will($this->returnValue(true))
+ ;
+ $handler->expects($this->any())
+ ->method('handle')
+ ->will($this->throwException(new \Exception('Some handler exception')))
+ ;
+ $logger->pushHandler($handler);
+ $logger->info('test');
+ }
}