Skip to content

Commit

Permalink
Add forwarding of formatter functions to nested handlers in Sampling,…
Browse files Browse the repository at this point in the history
… Filter and FingersCrossed handlers, and fix handling of callable factory handler config, fixes #1386, closes #1387
  • Loading branch information
Seldaek committed Nov 11, 2019
1 parent bb78e06 commit 65f1f30
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 36 deletions.
52 changes: 41 additions & 11 deletions src/Monolog/Handler/FilterHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;

/**
* Simple handler wrapper that filters records based on a list of levels
Expand Down Expand Up @@ -45,7 +46,7 @@ class FilterHandler extends AbstractHandler
protected $bubble;

/**
* @param callable|HandlerInterface $handler Handler or factory callable($record, $this).
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $filterHandler).
* @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 bool $bubble Whether the messages that are handled can bubble up the stack or not
Expand Down Expand Up @@ -104,21 +105,13 @@ public function handle(array $record)
return false;
}

// The same logic as in FingersCrossedHandler
if (!$this->handler instanceof HandlerInterface) {
$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
}

if ($this->processors) {
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
}
}

$this->handler->handle($record);
$this->getHandler($record)->handle($record);

return false === $this->bubble;
}
Expand All @@ -135,6 +128,43 @@ public function handleBatch(array $records)
}
}

$this->handler->handleBatch($filtered);
$this->getHandler($filtered[count($filtered) - 1])->handleBatch($filtered);
}

/**
* Return the nested handler
*
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
*
* @return HandlerInterface
*/
public function getHandler(array $record = null)
{
if (!$this->handler instanceof HandlerInterface) {
$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
}

return $this->handler;
}

/**
* {@inheritdoc}
*/
public function setFormatter(FormatterInterface $formatter)
{
$this->getHandler()->setFormatter($formatter);

return $this;
}

/**
* {@inheritdoc}
*/
public function getFormatter()
{
return $this->getHandler()->getFormatter();
}
}
58 changes: 44 additions & 14 deletions src/Monolog/Handler/FingersCrossedHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;

/**
* Buffers all records until a certain level is reached
Expand All @@ -39,7 +40,7 @@ class FingersCrossedHandler extends AbstractHandler
protected $passthruLevel;

/**
* @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler).
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $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 bool $bubble Whether the messages that are handled can bubble up the stack or not
Expand Down Expand Up @@ -88,15 +89,7 @@ public function activate()
if ($this->stopBuffering) {
$this->buffering = false;
}
if (!$this->handler instanceof HandlerInterface) {
$record = end($this->buffer) ?: null;

$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
}
$this->handler->handleBatch($this->buffer);
$this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer);
$this->buffer = array();
}

Expand All @@ -120,7 +113,7 @@ public function handle(array $record)
$this->activate();
}
} else {
$this->handler->handle($record);
$this->getHandler($record)->handle($record);
}

return false === $this->bubble;
Expand All @@ -140,8 +133,8 @@ public function reset()

parent::reset();

if ($this->handler instanceof ResettableInterface) {
$this->handler->reset();
if ($this->getHandler() instanceof ResettableInterface) {
$this->getHandler()->reset();
}
}

Expand All @@ -167,11 +160,48 @@ private function flushBuffer()
return $record['level'] >= $level;
});
if (count($this->buffer) > 0) {
$this->handler->handleBatch($this->buffer);
$this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer);
}
}

$this->buffer = array();
$this->buffering = true;
}

/**
* Return the nested handler
*
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
*
* @return HandlerInterface
*/
public function getHandler(array $record = null)
{
if (!$this->handler instanceof HandlerInterface) {
$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
}

return $this->handler;
}

/**
* {@inheritdoc}
*/
public function setFormatter(FormatterInterface $formatter)
{
$this->getHandler()->setFormatter($formatter);

return $this;
}

/**
* {@inheritdoc}
*/
public function getFormatter()
{
return $this->getHandler()->getFormatter();
}
}
53 changes: 42 additions & 11 deletions src/Monolog/Handler/SamplingHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;

/**
* Sampling handler
*
Expand Down Expand Up @@ -38,7 +40,7 @@ class SamplingHandler extends AbstractHandler
protected $factor;

/**
* @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler).
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $samplingHandler).
* @param int $factor Sample factor
*/
public function __construct($handler, $factor)
Expand All @@ -54,29 +56,58 @@ public function __construct($handler, $factor)

public function isHandling(array $record)
{
return $this->handler->isHandling($record);
return $this->getHandler($record)->isHandling($record);
}

public function handle(array $record)
{
if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
// The same logic as in FingersCrossedHandler
if (!$this->handler instanceof HandlerInterface) {
$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
}

if ($this->processors) {
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
}
}

$this->handler->handle($record);
$this->getHandler($record)->handle($record);
}

return false === $this->bubble;
}

/**
* Return the nested handler
*
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
*
* @return HandlerInterface
*/
public function getHandler(array $record = null)
{
if (!$this->handler instanceof HandlerInterface) {
$this->handler = call_user_func($this->handler, $record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
}

return $this->handler;
}

/**
* {@inheritdoc}
*/
public function setFormatter(FormatterInterface $formatter)
{
$this->getHandler()->setFormatter($formatter);

return $this;
}

/**
* {@inheritdoc}
*/
public function getFormatter()
{
return $this->getHandler()->getFormatter();
}
}

0 comments on commit 65f1f30

Please sign in to comment.