"Fossies" - the Fresh Open Source Software Archive

Member "grav/vendor/monolog/monolog/src/Monolog/Logger.php" (1 Sep 2020, 22341 Bytes) of package /linux/www/grav-v1.6.27.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Logger.php" see the Fossies "Dox" file reference documentation.

    1 <?php
    2 
    3 /*
    4  * This file is part of the Monolog package.
    5  *
    6  * (c) Jordi Boggiano <j.boggiano@seld.be>
    7  *
    8  * For the full copyright and license information, please view the LICENSE
    9  * file that was distributed with this source code.
   10  */
   11 
   12 namespace Monolog;
   13 
   14 use Monolog\Handler\HandlerInterface;
   15 use Monolog\Handler\StreamHandler;
   16 use Psr\Log\LoggerInterface;
   17 use Psr\Log\InvalidArgumentException;
   18 use Exception;
   19 
   20 /**
   21  * Monolog log channel
   22  *
   23  * It contains a stack of Handlers and a stack of Processors,
   24  * and uses them to store records that are added to it.
   25  *
   26  * @author Jordi Boggiano <j.boggiano@seld.be>
   27  */
   28 class Logger implements LoggerInterface, ResettableInterface
   29 {
   30     /**
   31      * Detailed debug information
   32      */
   33     const DEBUG = 100;
   34 
   35     /**
   36      * Interesting events
   37      *
   38      * Examples: User logs in, SQL logs.
   39      */
   40     const INFO = 200;
   41 
   42     /**
   43      * Uncommon events
   44      */
   45     const NOTICE = 250;
   46 
   47     /**
   48      * Exceptional occurrences that are not errors
   49      *
   50      * Examples: Use of deprecated APIs, poor use of an API,
   51      * undesirable things that are not necessarily wrong.
   52      */
   53     const WARNING = 300;
   54 
   55     /**
   56      * Runtime errors
   57      */
   58     const ERROR = 400;
   59 
   60     /**
   61      * Critical conditions
   62      *
   63      * Example: Application component unavailable, unexpected exception.
   64      */
   65     const CRITICAL = 500;
   66 
   67     /**
   68      * Action must be taken immediately
   69      *
   70      * Example: Entire website down, database unavailable, etc.
   71      * This should trigger the SMS alerts and wake you up.
   72      */
   73     const ALERT = 550;
   74 
   75     /**
   76      * Urgent alert.
   77      */
   78     const EMERGENCY = 600;
   79 
   80     /**
   81      * Monolog API version
   82      *
   83      * This is only bumped when API breaks are done and should
   84      * follow the major version of the library
   85      *
   86      * @var int
   87      */
   88     const API = 1;
   89 
   90     /**
   91      * Logging levels from syslog protocol defined in RFC 5424
   92      *
   93      * @var array $levels Logging levels
   94      */
   95     protected static $levels = array(
   96         self::DEBUG     => 'DEBUG',
   97         self::INFO      => 'INFO',
   98         self::NOTICE    => 'NOTICE',
   99         self::WARNING   => 'WARNING',
  100         self::ERROR     => 'ERROR',
  101         self::CRITICAL  => 'CRITICAL',
  102         self::ALERT     => 'ALERT',
  103         self::EMERGENCY => 'EMERGENCY',
  104     );
  105 
  106     /**
  107      * @var \DateTimeZone
  108      */
  109     protected static $timezone;
  110 
  111     /**
  112      * @var string
  113      */
  114     protected $name;
  115 
  116     /**
  117      * The handler stack
  118      *
  119      * @var HandlerInterface[]
  120      */
  121     protected $handlers;
  122 
  123     /**
  124      * Processors that will process all log records
  125      *
  126      * To process records of a single handler instead, add the processor on that specific handler
  127      *
  128      * @var callable[]
  129      */
  130     protected $processors;
  131 
  132     /**
  133      * @var bool
  134      */
  135     protected $microsecondTimestamps = true;
  136 
  137     /**
  138      * @var callable
  139      */
  140     protected $exceptionHandler;
  141 
  142     /**
  143      * @param string             $name       The logging channel
  144      * @param HandlerInterface[] $handlers   Optional stack of handlers, the first one in the array is called first, etc.
  145      * @param callable[]         $processors Optional array of processors
  146      */
  147     public function __construct($name, array $handlers = array(), array $processors = array())
  148     {
  149         $this->name = $name;
  150         $this->setHandlers($handlers);
  151         $this->processors = $processors;
  152     }
  153 
  154     /**
  155      * @return string
  156      */
  157     public function getName()
  158     {
  159         return $this->name;
  160     }
  161 
  162     /**
  163      * Return a new cloned instance with the name changed
  164      *
  165      * @return static
  166      */
  167     public function withName($name)
  168     {
  169         $new = clone $this;
  170         $new->name = $name;
  171 
  172         return $new;
  173     }
  174 
  175     /**
  176      * Pushes a handler on to the stack.
  177      *
  178      * @param  HandlerInterface $handler
  179      * @return $this
  180      */
  181     public function pushHandler(HandlerInterface $handler)
  182     {
  183         array_unshift($this->handlers, $handler);
  184 
  185         return $this;
  186     }
  187 
  188     /**
  189      * Pops a handler from the stack
  190      *
  191      * @return HandlerInterface
  192      */
  193     public function popHandler()
  194     {
  195         if (!$this->handlers) {
  196             throw new \LogicException('You tried to pop from an empty handler stack.');
  197         }
  198 
  199         return array_shift($this->handlers);
  200     }
  201 
  202     /**
  203      * Set handlers, replacing all existing ones.
  204      *
  205      * If a map is passed, keys will be ignored.
  206      *
  207      * @param  HandlerInterface[] $handlers
  208      * @return $this
  209      */
  210     public function setHandlers(array $handlers)
  211     {
  212         $this->handlers = array();
  213         foreach (array_reverse($handlers) as $handler) {
  214             $this->pushHandler($handler);
  215         }
  216 
  217         return $this;
  218     }
  219 
  220     /**
  221      * @return HandlerInterface[]
  222      */
  223     public function getHandlers()
  224     {
  225         return $this->handlers;
  226     }
  227 
  228     /**
  229      * Adds a processor on to the stack.
  230      *
  231      * @param  callable $callback
  232      * @return $this
  233      */
  234     public function pushProcessor($callback)
  235     {
  236         if (!is_callable($callback)) {
  237             throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given');
  238         }
  239         array_unshift($this->processors, $callback);
  240 
  241         return $this;
  242     }
  243 
  244     /**
  245      * Removes the processor on top of the stack and returns it.
  246      *
  247      * @return callable
  248      */
  249     public function popProcessor()
  250     {
  251         if (!$this->processors) {
  252             throw new \LogicException('You tried to pop from an empty processor stack.');
  253         }
  254 
  255         return array_shift($this->processors);
  256     }
  257 
  258     /**
  259      * @return callable[]
  260      */
  261     public function getProcessors()
  262     {
  263         return $this->processors;
  264     }
  265 
  266     /**
  267      * Control the use of microsecond resolution timestamps in the 'datetime'
  268      * member of new records.
  269      *
  270      * Generating microsecond resolution timestamps by calling
  271      * microtime(true), formatting the result via sprintf() and then parsing
  272      * the resulting string via \DateTime::createFromFormat() can incur
  273      * a measurable runtime overhead vs simple usage of DateTime to capture
  274      * a second resolution timestamp in systems which generate a large number
  275      * of log events.
  276      *
  277      * @param bool $micro True to use microtime() to create timestamps
  278      */
  279     public function useMicrosecondTimestamps($micro)
  280     {
  281         $this->microsecondTimestamps = (bool) $micro;
  282     }
  283 
  284     /**
  285      * Adds a log record.
  286      *
  287      * @param  int     $level   The logging level
  288      * @param  string  $message The log message
  289      * @param  array   $context The log context
  290      * @return bool Whether the record has been processed
  291      */
  292     public function addRecord($level, $message, array $context = array())
  293     {
  294         if (!$this->handlers) {
  295             $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG));
  296         }
  297 
  298         $levelName = static::getLevelName($level);
  299 
  300         // check if any handler will handle this message so we can return early and save cycles
  301         $handlerKey = null;
  302         reset($this->handlers);
  303         while ($handler = current($this->handlers)) {
  304             if ($handler->isHandling(array('level' => $level))) {
  305                 $handlerKey = key($this->handlers);
  306                 break;
  307             }
  308 
  309             next($this->handlers);
  310         }
  311 
  312         if (null === $handlerKey) {
  313             return false;
  314         }
  315 
  316         if (!static::$timezone) {
  317             static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC');
  318         }
  319 
  320         // php7.1+ always has microseconds enabled, so we do not need this hack
  321         if ($this->microsecondTimestamps && PHP_VERSION_ID < 70100) {
  322             $ts = \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone);
  323         } else {
  324             $ts = new \DateTime(null, static::$timezone);
  325         }
  326         $ts->setTimezone(static::$timezone);
  327 
  328         $record = array(
  329             'message' => (string) $message,
  330             'context' => $context,
  331             'level' => $level,
  332             'level_name' => $levelName,
  333             'channel' => $this->name,
  334             'datetime' => $ts,
  335             'extra' => array(),
  336         );
  337 
  338         try {
  339             foreach ($this->processors as $processor) {
  340                 $record = call_user_func($processor, $record);
  341             }
  342 
  343             while ($handler = current($this->handlers)) {
  344                 if (true === $handler->handle($record)) {
  345                     break;
  346                 }
  347 
  348                 next($this->handlers);
  349             }
  350         } catch (Exception $e) {
  351             $this->handleException($e, $record);
  352         }
  353 
  354         return true;
  355     }
  356 
  357     /**
  358      * Ends a log cycle and frees all resources used by handlers.
  359      *
  360      * Closing a Handler means flushing all buffers and freeing any open resources/handles.
  361      * Handlers that have been closed should be able to accept log records again and re-open
  362      * themselves on demand, but this may not always be possible depending on implementation.
  363      *
  364      * This is useful at the end of a request and will be called automatically on every handler
  365      * when they get destructed.
  366      */
  367     public function close()
  368     {
  369         foreach ($this->handlers as $handler) {
  370             if (method_exists($handler, 'close')) {
  371                 $handler->close();
  372             }
  373         }
  374     }
  375 
  376     /**
  377      * Ends a log cycle and resets all handlers and processors to their initial state.
  378      *
  379      * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
  380      * state, and getting it back to a state in which it can receive log records again.
  381      *
  382      * This is useful in case you want to avoid logs leaking between two requests or jobs when you
  383      * have a long running process like a worker or an application server serving multiple requests
  384      * in one process.
  385      */
  386     public function reset()
  387     {
  388         foreach ($this->handlers as $handler) {
  389             if ($handler instanceof ResettableInterface) {
  390                 $handler->reset();
  391             }
  392         }
  393 
  394         foreach ($this->processors as $processor) {
  395             if ($processor instanceof ResettableInterface) {
  396                 $processor->reset();
  397             }
  398         }
  399     }
  400 
  401     /**
  402      * Adds a log record at the DEBUG level.
  403      *
  404      * @param  string $message The log message
  405      * @param  array  $context The log context
  406      * @return bool   Whether the record has been processed
  407      */
  408     public function addDebug($message, array $context = array())
  409     {
  410         return $this->addRecord(static::DEBUG, $message, $context);
  411     }
  412 
  413     /**
  414      * Adds a log record at the INFO level.
  415      *
  416      * @param  string $message The log message
  417      * @param  array  $context The log context
  418      * @return bool   Whether the record has been processed
  419      */
  420     public function addInfo($message, array $context = array())
  421     {
  422         return $this->addRecord(static::INFO, $message, $context);
  423     }
  424 
  425     /**
  426      * Adds a log record at the NOTICE level.
  427      *
  428      * @param  string $message The log message
  429      * @param  array  $context The log context
  430      * @return bool   Whether the record has been processed
  431      */
  432     public function addNotice($message, array $context = array())
  433     {
  434         return $this->addRecord(static::NOTICE, $message, $context);
  435     }
  436 
  437     /**
  438      * Adds a log record at the WARNING level.
  439      *
  440      * @param  string $message The log message
  441      * @param  array  $context The log context
  442      * @return bool   Whether the record has been processed
  443      */
  444     public function addWarning($message, array $context = array())
  445     {
  446         return $this->addRecord(static::WARNING, $message, $context);
  447     }
  448 
  449     /**
  450      * Adds a log record at the ERROR level.
  451      *
  452      * @param  string $message The log message
  453      * @param  array  $context The log context
  454      * @return bool   Whether the record has been processed
  455      */
  456     public function addError($message, array $context = array())
  457     {
  458         return $this->addRecord(static::ERROR, $message, $context);
  459     }
  460 
  461     /**
  462      * Adds a log record at the CRITICAL level.
  463      *
  464      * @param  string $message The log message
  465      * @param  array  $context The log context
  466      * @return bool   Whether the record has been processed
  467      */
  468     public function addCritical($message, array $context = array())
  469     {
  470         return $this->addRecord(static::CRITICAL, $message, $context);
  471     }
  472 
  473     /**
  474      * Adds a log record at the ALERT level.
  475      *
  476      * @param  string $message The log message
  477      * @param  array  $context The log context
  478      * @return bool   Whether the record has been processed
  479      */
  480     public function addAlert($message, array $context = array())
  481     {
  482         return $this->addRecord(static::ALERT, $message, $context);
  483     }
  484 
  485     /**
  486      * Adds a log record at the EMERGENCY level.
  487      *
  488      * @param  string $message The log message
  489      * @param  array  $context The log context
  490      * @return bool   Whether the record has been processed
  491      */
  492     public function addEmergency($message, array $context = array())
  493     {
  494         return $this->addRecord(static::EMERGENCY, $message, $context);
  495     }
  496 
  497     /**
  498      * Gets all supported logging levels.
  499      *
  500      * @return array Assoc array with human-readable level names => level codes.
  501      */
  502     public static function getLevels()
  503     {
  504         return array_flip(static::$levels);
  505     }
  506 
  507     /**
  508      * Gets the name of the logging level.
  509      *
  510      * @param  int    $level
  511      * @return string
  512      */
  513     public static function getLevelName($level)
  514     {
  515         if (!isset(static::$levels[$level])) {
  516             throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels)));
  517         }
  518 
  519         return static::$levels[$level];
  520     }
  521 
  522     /**
  523      * Converts PSR-3 levels to Monolog ones if necessary
  524      *
  525      * @param string|int Level number (monolog) or name (PSR-3)
  526      * @return int
  527      */
  528     public static function toMonologLevel($level)
  529     {
  530         if (is_string($level)) {
  531             // Contains chars of all log levels and avoids using strtoupper() which may have
  532             // strange results depending on locale (for example, "i" will become "İ")
  533             $upper = strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY');
  534             if (defined(__CLASS__.'::'.$upper)) {
  535                 return constant(__CLASS__ . '::' . $upper);
  536             }
  537         }
  538 
  539         return $level;
  540     }
  541 
  542     /**
  543      * Checks whether the Logger has a handler that listens on the given level
  544      *
  545      * @param  int     $level
  546      * @return bool
  547      */
  548     public function isHandling($level)
  549     {
  550         $record = array(
  551             'level' => $level,
  552         );
  553 
  554         foreach ($this->handlers as $handler) {
  555             if ($handler->isHandling($record)) {
  556                 return true;
  557             }
  558         }
  559 
  560         return false;
  561     }
  562 
  563     /**
  564      * Set a custom exception handler
  565      *
  566      * @param  callable $callback
  567      * @return $this
  568      */
  569     public function setExceptionHandler($callback)
  570     {
  571         if (!is_callable($callback)) {
  572             throw new \InvalidArgumentException('Exception handler must be valid callable (callback or object with an __invoke method), '.var_export($callback, true).' given');
  573         }
  574         $this->exceptionHandler = $callback;
  575 
  576         return $this;
  577     }
  578 
  579     /**
  580      * @return callable
  581      */
  582     public function getExceptionHandler()
  583     {
  584         return $this->exceptionHandler;
  585     }
  586 
  587     /**
  588      * Delegates exception management to the custom exception handler,
  589      * or throws the exception if no custom handler is set.
  590      */
  591     protected function handleException(Exception $e, array $record)
  592     {
  593         if (!$this->exceptionHandler) {
  594             throw $e;
  595         }
  596 
  597         call_user_func($this->exceptionHandler, $e, $record);
  598     }
  599 
  600     /**
  601      * Adds a log record at an arbitrary level.
  602      *
  603      * This method allows for compatibility with common interfaces.
  604      *
  605      * @param  mixed   $level   The log level
  606      * @param  string $message The log message
  607      * @param  array  $context The log context
  608      * @return bool   Whether the record has been processed
  609      */
  610     public function log($level, $message, array $context = array())
  611     {
  612         $level = static::toMonologLevel($level);
  613 
  614         return $this->addRecord($level, $message, $context);
  615     }
  616 
  617     /**
  618      * Adds a log record at the DEBUG level.
  619      *
  620      * This method allows for compatibility with common interfaces.
  621      *
  622      * @param  string $message The log message
  623      * @param  array  $context The log context
  624      * @return bool   Whether the record has been processed
  625      */
  626     public function debug($message, array $context = array())
  627     {
  628         return $this->addRecord(static::DEBUG, $message, $context);
  629     }
  630 
  631     /**
  632      * Adds a log record at the INFO level.
  633      *
  634      * This method allows for compatibility with common interfaces.
  635      *
  636      * @param  string $message The log message
  637      * @param  array  $context The log context
  638      * @return bool   Whether the record has been processed
  639      */
  640     public function info($message, array $context = array())
  641     {
  642         return $this->addRecord(static::INFO, $message, $context);
  643     }
  644 
  645     /**
  646      * Adds a log record at the NOTICE level.
  647      *
  648      * This method allows for compatibility with common interfaces.
  649      *
  650      * @param  string $message The log message
  651      * @param  array  $context The log context
  652      * @return bool   Whether the record has been processed
  653      */
  654     public function notice($message, array $context = array())
  655     {
  656         return $this->addRecord(static::NOTICE, $message, $context);
  657     }
  658 
  659     /**
  660      * Adds a log record at the WARNING level.
  661      *
  662      * This method allows for compatibility with common interfaces.
  663      *
  664      * @param  string $message The log message
  665      * @param  array  $context The log context
  666      * @return bool   Whether the record has been processed
  667      */
  668     public function warn($message, array $context = array())
  669     {
  670         return $this->addRecord(static::WARNING, $message, $context);
  671     }
  672 
  673     /**
  674      * Adds a log record at the WARNING level.
  675      *
  676      * This method allows for compatibility with common interfaces.
  677      *
  678      * @param  string $message The log message
  679      * @param  array  $context The log context
  680      * @return bool   Whether the record has been processed
  681      */
  682     public function warning($message, array $context = array())
  683     {
  684         return $this->addRecord(static::WARNING, $message, $context);
  685     }
  686 
  687     /**
  688      * Adds a log record at the ERROR level.
  689      *
  690      * This method allows for compatibility with common interfaces.
  691      *
  692      * @param  string $message The log message
  693      * @param  array  $context The log context
  694      * @return bool   Whether the record has been processed
  695      */
  696     public function err($message, array $context = array())
  697     {
  698         return $this->addRecord(static::ERROR, $message, $context);
  699     }
  700 
  701     /**
  702      * Adds a log record at the ERROR level.
  703      *
  704      * This method allows for compatibility with common interfaces.
  705      *
  706      * @param  string $message The log message
  707      * @param  array  $context The log context
  708      * @return bool   Whether the record has been processed
  709      */
  710     public function error($message, array $context = array())
  711     {
  712         return $this->addRecord(static::ERROR, $message, $context);
  713     }
  714 
  715     /**
  716      * Adds a log record at the CRITICAL level.
  717      *
  718      * This method allows for compatibility with common interfaces.
  719      *
  720      * @param  string $message The log message
  721      * @param  array  $context The log context
  722      * @return bool   Whether the record has been processed
  723      */
  724     public function crit($message, array $context = array())
  725     {
  726         return $this->addRecord(static::CRITICAL, $message, $context);
  727     }
  728 
  729     /**
  730      * Adds a log record at the CRITICAL level.
  731      *
  732      * This method allows for compatibility with common interfaces.
  733      *
  734      * @param  string $message The log message
  735      * @param  array  $context The log context
  736      * @return bool   Whether the record has been processed
  737      */
  738     public function critical($message, array $context = array())
  739     {
  740         return $this->addRecord(static::CRITICAL, $message, $context);
  741     }
  742 
  743     /**
  744      * Adds a log record at the ALERT level.
  745      *
  746      * This method allows for compatibility with common interfaces.
  747      *
  748      * @param  string $message The log message
  749      * @param  array  $context The log context
  750      * @return bool   Whether the record has been processed
  751      */
  752     public function alert($message, array $context = array())
  753     {
  754         return $this->addRecord(static::ALERT, $message, $context);
  755     }
  756 
  757     /**
  758      * Adds a log record at the EMERGENCY level.
  759      *
  760      * This method allows for compatibility with common interfaces.
  761      *
  762      * @param  string $message The log message
  763      * @param  array  $context The log context
  764      * @return bool   Whether the record has been processed
  765      */
  766     public function emerg($message, array $context = array())
  767     {
  768         return $this->addRecord(static::EMERGENCY, $message, $context);
  769     }
  770 
  771     /**
  772      * Adds a log record at the EMERGENCY level.
  773      *
  774      * This method allows for compatibility with common interfaces.
  775      *
  776      * @param  string $message The log message
  777      * @param  array  $context The log context
  778      * @return bool   Whether the record has been processed
  779      */
  780     public function emergency($message, array $context = array())
  781     {
  782         return $this->addRecord(static::EMERGENCY, $message, $context);
  783     }
  784 
  785     /**
  786      * Set the timezone to be used for the timestamp of log records.
  787      *
  788      * This is stored globally for all Logger instances
  789      *
  790      * @param \DateTimeZone $tz Timezone object
  791      */
  792     public static function setTimezone(\DateTimeZone $tz)
  793     {
  794         self::$timezone = $tz;
  795     }
  796 }