// Create the logger
$logger = new Logger('my_logger');
// Now add some handlers
$handler = new StreamHandler('my_app.log', Logger::DEBUG);
$logger->pushHandler($handler);
$logger->pushProcessor(function ($record) {
$record['extra']['dummy'] = 'Hello world!';
return $record;
});
// You can now use your logger
$logger->addInfo('My logger is now ready');
англ. Object Calisthenics. Calisthenics — зарядка, гимнастика.
/**
* The handler stack
*
* @var HandlerInterface[]
*/
protected $handlers;
public function isHandling(int $level): bool
{
$record = array(
'level' => $level,
);
foreach ($this->handlers as $handler) {
if ($handler->isHandling($record)) {
return true;
}
}
return false;
}
/**
* The handler stack
*
* @var HandlerStack
*/
protected $handlers;
public function isHandling(int $level): bool
{
return $this->handlers->isHandling($level);
}
/**
* The handler stack
*
* @var HandlerInterface[]
*/
protected $handlers;
public function isHandling($record): bool
{
foreach ($this->handlers as $handler) {
if ($handler->isHandling($record)) {
return true;
}
}
return false;
}
/**
* The handler stack
*
* @var HandlerStack
*/
protected $handlers;
public function isHandling(int $level): bool
{
return $this->handlers->isHandling($level);
}
/**
* Processors that will process all log records
*
* To process records of a single handler instead, add the processor on that specific handler
* @var callable[]
*/
protected $processors;
public function pushProcessor(callable $callback): self
{
array_unshift($this->processors, $callback);
return $this;
}
...
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
}
/**
* The procesors stack stack
*
* To process records of a single handler instead, add the processor on that specific handler
* @var ProcessorStack
*/
protected $processors;
public function pushProcessor(callable $callback): self
{
$this->processors->push($callback);
return $this;
}
...
$record = $this->processors->process($record);
/**
* Processors that will process all log records
*
* To process records of a single handler instead, add the processor on that specific handler
* @var callable[]
*/
protected $processors;
public function pushProcessor(callable $callback): self
{
array_unshift($this->processors, $callback);
return $this;
}
protected function processRecord(array $record)
{
foreach ($this->processors as $processor) {
$record = $processor($record);
}
return $record;
}
-30 LOC
-4 теста
public function addRecord(int $level, string $message, array $context = array()): bool
public function isHandling(array $record): bool
{
return $record['level'] >= $this->level;
}
public static function toMonologLevel($level): int
{
if (is_string($level)) {
if (defined(__CLASS__.'::'.strtoupper($level))) {
return constant(__CLASS__.'::'.strtoupper($level));
}
throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels)));
return $level;
}
/**
* This is a static variable and not a constant to serve as an extension point for custom levels
*
* @var string[] $levels Logging levels with the levels as key
*/
protected static $levels = [
self::DEBUG => 'DEBUG',
self::INFO => 'INFO',
.....
class LogLevel implements LogLevelInterface
{
....
public function __toString()
{
$name = array_search($this->level, self::$levels);
if ($name !== false) {
return strtoupper($name);
}
return 'undefined';
}
....
/**
* @inheritdocs
*/
public function includes($level): bool
{
if ($level instanceof LogLevel) {
return $level->getLevel() >= $this->level;
}
return $level >= $this->level;
}
public function __construct($serverData = null)
{
if (null === $serverData) {
$this->serverData =& $_SERVER;
} elseif (is_array($serverData)) {
$this->serverData = $serverData;
} else {
throw new \UnexpectedValueException('$serverData ....');
}
}
public function __construct($serverData = null)
{
if (null === $serverData) {
$serverData =& $_SERVER;
}
if (!is_array($serverData)) {
throw new \UnexpectedValueException('$serverData ....');
}
$this->serverData =& $serverData;
}
/**
* @var bool
*/
protected $microsecondTimestamps = false;
/**
* @var DateTimeZone
*/
protected $timezone;
if ($this->microsecondTimestamps) {
$ts = \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), $this->timezone);
} else {
$ts = new \DateTime('', $this->timezone);
}
$ts->setTimezone($this->timezone);
class DateTimeProcessor
{
/**
* @var bool
*/
protected $microsecondTimestamps = false;
/**
* @var DateTimeZone
*/
protected $timezone;
public function __construct(DateTimeZone $timezone = null)
...
protected $dateTimeProcessor;
public function __construct(string $name, array $handlers = array(), array $processors = array(), DateTimeZone $timezone = null)
{
parent::__construct($name, $handlers, $processors);
// BC compatible date time
$this->dateTimeProcessor = new DateTimeProcessor($timezone);
$this->pushProcessor($this->dateTimeProcessor);
}
-class FilterHandler extends Handler implements ProcessableHandlerInterface
{
use ProcessableHandlerTrait;
/**
* Whether the messages that are handled can bubble up the stack or not
*
* @var Boolean
*/
protected $bubble;
public function handle(array $record): bool
{
...
if ($this->processors) {
$record = $this->processRecord($record);
}
...
return false === $this->bubble;
}
abstract class GeneralHandler extends Handler
{
/*
*
* @var ProcessorStack
*/
protected $processors;
protected $bubble = true;
public function handle(array $record): bool
{
if (!$this->isHandling($record)) {
return false;
}
$record = $this->processors->process($record);
$this->postProcess($record);
return false === $this->bubble;
}
class FilterHandler extends GeneralHandler
class GroupHandler extends GeneralHandler
class AbstractProcessingHandler extends GeneralHandler
class SamplingHandler extends GeneralHandler
и результаты интересные