+ */
+class MercurialProcessor implements ProcessorInterface
+{
+ private $level;
+ private static $cache;
+
+ public function __construct($level = Logger::DEBUG)
+ {
+ $this->level = Logger::toMonologLevel($level);
+ }
+
+ /**
+ * @param array $record
+ * @return array
+ */
+ public function __invoke(array $record)
+ {
+ // return if the level is not high enough
+ if ($record['level'] < $this->level) {
+ return $record;
+ }
+
+ $record['extra']['hg'] = self::getMercurialInfo();
+
+ return $record;
+ }
+
+ private static function getMercurialInfo()
+ {
+ if (self::$cache) {
+ return self::$cache;
+ }
+
+ $result = explode(' ', trim(`hg id -nb`));
+ if (count($result) >= 3) {
+ return self::$cache = array(
+ 'branch' => $result[1],
+ 'revision' => $result[2],
+ );
+ }
+
+ return self::$cache = array();
+ }
+}
diff --git a/lam/lib/3rdParty/Monolog/Processor/ProcessIdProcessor.php b/lam/lib/3rdParty/Monolog/Processor/ProcessIdProcessor.php
new file mode 100644
index 00000000..66b80fbb
--- /dev/null
+++ b/lam/lib/3rdParty/Monolog/Processor/ProcessIdProcessor.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+/**
+ * Adds value of getmypid into records
+ *
+ * @author Andreas Hörnicke
+ */
+class ProcessIdProcessor implements ProcessorInterface
+{
+ /**
+ * @param array $record
+ * @return array
+ */
+ public function __invoke(array $record)
+ {
+ $record['extra']['process_id'] = getmypid();
+
+ return $record;
+ }
+}
diff --git a/lam/lib/3rdParty/Monolog/Processor/ProcessorInterface.php b/lam/lib/3rdParty/Monolog/Processor/ProcessorInterface.php
new file mode 100644
index 00000000..7e64d4df
--- /dev/null
+++ b/lam/lib/3rdParty/Monolog/Processor/ProcessorInterface.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+/**
+ * An optional interface to allow labelling Monolog processors.
+ *
+ * @author Nicolas Grekas
+ */
+interface ProcessorInterface
+{
+ /**
+ * @return array The processed records
+ */
+ public function __invoke(array $records);
+}
diff --git a/lam/lib/3rdParty/Monolog/Processor/PsrLogMessageProcessor.php b/lam/lib/3rdParty/Monolog/Processor/PsrLogMessageProcessor.php
new file mode 100644
index 00000000..00885054
--- /dev/null
+++ b/lam/lib/3rdParty/Monolog/Processor/PsrLogMessageProcessor.php
@@ -0,0 +1,50 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+use Monolog\Utils;
+
+/**
+ * Processes a record's message according to PSR-3 rules
+ *
+ * It replaces {foo} with the value from $context['foo']
+ *
+ * @author Jordi Boggiano
+ */
+class PsrLogMessageProcessor implements ProcessorInterface
+{
+ /**
+ * @param array $record
+ * @return array
+ */
+ public function __invoke(array $record)
+ {
+ if (false === strpos($record['message'], '{')) {
+ return $record;
+ }
+
+ $replacements = array();
+ foreach ($record['context'] as $key => $val) {
+ if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) {
+ $replacements['{'.$key.'}'] = $val;
+ } elseif (is_object($val)) {
+ $replacements['{'.$key.'}'] = '[object '.Utils::getClass($val).']';
+ } else {
+ $replacements['{'.$key.'}'] = '['.gettype($val).']';
+ }
+ }
+
+ $record['message'] = strtr($record['message'], $replacements);
+
+ return $record;
+ }
+}
diff --git a/lam/lib/3rdParty/Monolog/Processor/TagProcessor.php b/lam/lib/3rdParty/Monolog/Processor/TagProcessor.php
new file mode 100644
index 00000000..615a4d99
--- /dev/null
+++ b/lam/lib/3rdParty/Monolog/Processor/TagProcessor.php
@@ -0,0 +1,44 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+/**
+ * Adds a tags array into record
+ *
+ * @author Martijn Riemers
+ */
+class TagProcessor implements ProcessorInterface
+{
+ private $tags;
+
+ public function __construct(array $tags = array())
+ {
+ $this->setTags($tags);
+ }
+
+ public function addTags(array $tags = array())
+ {
+ $this->tags = array_merge($this->tags, $tags);
+ }
+
+ public function setTags(array $tags = array())
+ {
+ $this->tags = $tags;
+ }
+
+ public function __invoke(array $record)
+ {
+ $record['extra']['tags'] = $this->tags;
+
+ return $record;
+ }
+}
diff --git a/lam/lib/3rdParty/Monolog/Processor/UidProcessor.php b/lam/lib/3rdParty/Monolog/Processor/UidProcessor.php
new file mode 100644
index 00000000..d1f708cf
--- /dev/null
+++ b/lam/lib/3rdParty/Monolog/Processor/UidProcessor.php
@@ -0,0 +1,59 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+use Monolog\ResettableInterface;
+
+/**
+ * Adds a unique identifier into records
+ *
+ * @author Simon Mönch
+ */
+class UidProcessor implements ProcessorInterface, ResettableInterface
+{
+ private $uid;
+
+ public function __construct($length = 7)
+ {
+ if (!is_int($length) || $length > 32 || $length < 1) {
+ throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32');
+ }
+
+
+ $this->uid = $this->generateUid($length);
+ }
+
+ public function __invoke(array $record)
+ {
+ $record['extra']['uid'] = $this->uid;
+
+ return $record;
+ }
+
+ /**
+ * @return string
+ */
+ public function getUid()
+ {
+ return $this->uid;
+ }
+
+ public function reset()
+ {
+ $this->uid = $this->generateUid(strlen($this->uid));
+ }
+
+ private function generateUid($length)
+ {
+ return substr(hash('md5', uniqid('', true)), 0, $length);
+ }
+}
diff --git a/lam/lib/3rdParty/Monolog/Processor/WebProcessor.php b/lam/lib/3rdParty/Monolog/Processor/WebProcessor.php
new file mode 100644
index 00000000..684188f6
--- /dev/null
+++ b/lam/lib/3rdParty/Monolog/Processor/WebProcessor.php
@@ -0,0 +1,113 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+/**
+ * Injects url/method and remote IP of the current web request in all records
+ *
+ * @author Jordi Boggiano
+ */
+class WebProcessor implements ProcessorInterface
+{
+ /**
+ * @var array|\ArrayAccess
+ */
+ protected $serverData;
+
+ /**
+ * Default fields
+ *
+ * Array is structured as [key in record.extra => key in $serverData]
+ *
+ * @var array
+ */
+ protected $extraFields = array(
+ 'url' => 'REQUEST_URI',
+ 'ip' => 'REMOTE_ADDR',
+ 'http_method' => 'REQUEST_METHOD',
+ 'server' => 'SERVER_NAME',
+ 'referrer' => 'HTTP_REFERER',
+ );
+
+ /**
+ * @param array|\ArrayAccess $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data
+ * @param array|null $extraFields Field names and the related key inside $serverData to be added. If not provided it defaults to: url, ip, http_method, server, referrer
+ */
+ public function __construct($serverData = null, array $extraFields = null)
+ {
+ if (null === $serverData) {
+ $this->serverData = &$_SERVER;
+ } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) {
+ $this->serverData = $serverData;
+ } else {
+ throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.');
+ }
+
+ if (null !== $extraFields) {
+ if (isset($extraFields[0])) {
+ foreach (array_keys($this->extraFields) as $fieldName) {
+ if (!in_array($fieldName, $extraFields)) {
+ unset($this->extraFields[$fieldName]);
+ }
+ }
+ } else {
+ $this->extraFields = $extraFields;
+ }
+ }
+ }
+
+ /**
+ * @param array $record
+ * @return array
+ */
+ public function __invoke(array $record)
+ {
+ // skip processing if for some reason request data
+ // is not present (CLI or wonky SAPIs)
+ if (!isset($this->serverData['REQUEST_URI'])) {
+ return $record;
+ }
+
+ $record['extra'] = $this->appendExtraFields($record['extra']);
+
+ return $record;
+ }
+
+ /**
+ * @param string $extraName
+ * @param string $serverName
+ * @return $this
+ */
+ public function addExtraField($extraName, $serverName)
+ {
+ $this->extraFields[$extraName] = $serverName;
+
+ return $this;
+ }
+
+ /**
+ * @param array $extra
+ * @return array
+ */
+ private function appendExtraFields(array $extra)
+ {
+ foreach ($this->extraFields as $extraName => $serverName) {
+ $extra[$extraName] = isset($this->serverData[$serverName]) ? $this->serverData[$serverName] : null;
+ }
+
+ if (isset($this->serverData['UNIQUE_ID'])) {
+ $extra['unique_id'] = $this->serverData['UNIQUE_ID'];
+ }
+
+ return $extra;
+ }
+}
diff --git a/lam/lib/3rdParty/Monolog/Registry.php b/lam/lib/3rdParty/Monolog/Registry.php
new file mode 100644
index 00000000..159b751c
--- /dev/null
+++ b/lam/lib/3rdParty/Monolog/Registry.php
@@ -0,0 +1,134 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog;
+
+use InvalidArgumentException;
+
+/**
+ * Monolog log registry
+ *
+ * Allows to get `Logger` instances in the global scope
+ * via static method calls on this class.
+ *
+ *
+ * $application = new Monolog\Logger('application');
+ * $api = new Monolog\Logger('api');
+ *
+ * Monolog\Registry::addLogger($application);
+ * Monolog\Registry::addLogger($api);
+ *
+ * function testLogger()
+ * {
+ * Monolog\Registry::api()->addError('Sent to $api Logger instance');
+ * Monolog\Registry::application()->addError('Sent to $application Logger instance');
+ * }
+ *
+ *
+ * @author Tomas Tatarko
+ */
+class Registry
+{
+ /**
+ * List of all loggers in the registry (by named indexes)
+ *
+ * @var Logger[]
+ */
+ private static $loggers = array();
+
+ /**
+ * Adds new logging channel to the registry
+ *
+ * @param Logger $logger Instance of the logging channel
+ * @param string|null $name Name of the logging channel ($logger->getName() by default)
+ * @param bool $overwrite Overwrite instance in the registry if the given name already exists?
+ * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists
+ */
+ public static function addLogger(Logger $logger, $name = null, $overwrite = false)
+ {
+ $name = $name ?: $logger->getName();
+
+ if (isset(self::$loggers[$name]) && !$overwrite) {
+ throw new InvalidArgumentException('Logger with the given name already exists');
+ }
+
+ self::$loggers[$name] = $logger;
+ }
+
+ /**
+ * Checks if such logging channel exists by name or instance
+ *
+ * @param string|Logger $logger Name or logger instance
+ */
+ public static function hasLogger($logger)
+ {
+ if ($logger instanceof Logger) {
+ $index = array_search($logger, self::$loggers, true);
+
+ return false !== $index;
+ } else {
+ return isset(self::$loggers[$logger]);
+ }
+ }
+
+ /**
+ * Removes instance from registry by name or instance
+ *
+ * @param string|Logger $logger Name or logger instance
+ */
+ public static function removeLogger($logger)
+ {
+ if ($logger instanceof Logger) {
+ if (false !== ($idx = array_search($logger, self::$loggers, true))) {
+ unset(self::$loggers[$idx]);
+ }
+ } else {
+ unset(self::$loggers[$logger]);
+ }
+ }
+
+ /**
+ * Clears the registry
+ */
+ public static function clear()
+ {
+ self::$loggers = array();
+ }
+
+ /**
+ * Gets Logger instance from the registry
+ *
+ * @param string $name Name of the requested Logger instance
+ * @throws \InvalidArgumentException If named Logger instance is not in the registry
+ * @return Logger Requested instance of Logger
+ */
+ public static function getInstance($name)
+ {
+ if (!isset(self::$loggers[$name])) {
+ throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name));
+ }
+
+ return self::$loggers[$name];
+ }
+
+ /**
+ * Gets Logger instance from the registry via static method call
+ *
+ * @param string $name Name of the requested Logger instance
+ * @param array $arguments Arguments passed to static method call
+ * @throws \InvalidArgumentException If named Logger instance is not in the registry
+ * @return Logger Requested instance of Logger
+ */
+ public static function __callStatic($name, $arguments)
+ {
+ return self::getInstance($name);
+ }
+}
diff --git a/lam/lib/3rdParty/Monolog/ResettableInterface.php b/lam/lib/3rdParty/Monolog/ResettableInterface.php
new file mode 100644
index 00000000..635bc77d
--- /dev/null
+++ b/lam/lib/3rdParty/Monolog/ResettableInterface.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog;
+
+/**
+ * Handler or Processor implementing this interface will be reset when Logger::reset() is called.
+ *
+ * Resetting ends a log cycle gets them back to their initial state.
+ *
+ * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
+ * state, and getting it back to a state in which it can receive log records again.
+ *
+ * This is useful in case you want to avoid logs leaking between two requests or jobs when you
+ * have a long running process like a worker or an application server serving multiple requests
+ * in one process.
+ *
+ * @author Grégoire Pineau
+ */
+interface ResettableInterface
+{
+ public function reset();
+}
diff --git a/lam/lib/3rdParty/Monolog/SignalHandler.php b/lam/lib/3rdParty/Monolog/SignalHandler.php
new file mode 100644
index 00000000..d5907805
--- /dev/null
+++ b/lam/lib/3rdParty/Monolog/SignalHandler.php
@@ -0,0 +1,115 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog;
+
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+use ReflectionExtension;
+
+/**
+ * Monolog POSIX signal handler
+ *
+ * @author Robert Gust-Bardon
+ */
+class SignalHandler
+{
+ private $logger;
+
+ private $previousSignalHandler = array();
+ private $signalLevelMap = array();
+ private $signalRestartSyscalls = array();
+
+ public function __construct(LoggerInterface $logger)
+ {
+ $this->logger = $logger;
+ }
+
+ public function registerSignalHandler($signo, $level = LogLevel::CRITICAL, $callPrevious = true, $restartSyscalls = true, $async = true)
+ {
+ if (!extension_loaded('pcntl') || !function_exists('pcntl_signal')) {
+ return $this;
+ }
+
+ if ($callPrevious) {
+ if (function_exists('pcntl_signal_get_handler')) {
+ $handler = pcntl_signal_get_handler($signo);
+ if ($handler === false) {
+ return $this;
+ }
+ $this->previousSignalHandler[$signo] = $handler;
+ } else {
+ $this->previousSignalHandler[$signo] = true;
+ }
+ } else {
+ unset($this->previousSignalHandler[$signo]);
+ }
+ $this->signalLevelMap[$signo] = $level;
+ $this->signalRestartSyscalls[$signo] = $restartSyscalls;
+
+ if (function_exists('pcntl_async_signals') && $async !== null) {
+ pcntl_async_signals($async);
+ }
+
+ pcntl_signal($signo, array($this, 'handleSignal'), $restartSyscalls);
+
+ return $this;
+ }
+
+ public function handleSignal($signo, array $siginfo = null)
+ {
+ static $signals = array();
+
+ if (!$signals && extension_loaded('pcntl')) {
+ $pcntl = new ReflectionExtension('pcntl');
+ $constants = $pcntl->getConstants();
+ if (!$constants) {
+ // HHVM 3.24.2 returns an empty array.
+ $constants = get_defined_constants(true);
+ $constants = $constants['Core'];
+ }
+ foreach ($constants as $name => $value) {
+ if (substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && is_int($value)) {
+ $signals[$value] = $name;
+ }
+ }
+ unset($constants);
+ }
+
+ $level = isset($this->signalLevelMap[$signo]) ? $this->signalLevelMap[$signo] : LogLevel::CRITICAL;
+ $signal = isset($signals[$signo]) ? $signals[$signo] : $signo;
+ $context = isset($siginfo) ? $siginfo : array();
+ $this->logger->log($level, sprintf('Program received signal %s', $signal), $context);
+
+ if (!isset($this->previousSignalHandler[$signo])) {
+ return;
+ }
+
+ if ($this->previousSignalHandler[$signo] === true || $this->previousSignalHandler[$signo] === SIG_DFL) {
+ if (extension_loaded('pcntl') && function_exists('pcntl_signal') && function_exists('pcntl_sigprocmask') && function_exists('pcntl_signal_dispatch')
+ && extension_loaded('posix') && function_exists('posix_getpid') && function_exists('posix_kill')) {
+ $restartSyscalls = isset($this->restartSyscalls[$signo]) ? $this->restartSyscalls[$signo] : true;
+ pcntl_signal($signo, SIG_DFL, $restartSyscalls);
+ pcntl_sigprocmask(SIG_UNBLOCK, array($signo), $oldset);
+ posix_kill(posix_getpid(), $signo);
+ pcntl_signal_dispatch();
+ pcntl_sigprocmask(SIG_SETMASK, $oldset);
+ pcntl_signal($signo, array($this, 'handleSignal'), $restartSyscalls);
+ }
+ } elseif (is_callable($this->previousSignalHandler[$signo])) {
+ if (PHP_VERSION_ID >= 70100) {
+ $this->previousSignalHandler[$signo]($signo, $siginfo);
+ } else {
+ $this->previousSignalHandler[$signo]($signo);
+ }
+ }
+ }
+}
diff --git a/lam/lib/3rdParty/Monolog/Utils.php b/lam/lib/3rdParty/Monolog/Utils.php
new file mode 100644
index 00000000..eb9be863
--- /dev/null
+++ b/lam/lib/3rdParty/Monolog/Utils.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog;
+
+class Utils
+{
+ /**
+ * @internal
+ */
+ public static function getClass($object)
+ {
+ $class = \get_class($object);
+
+ return 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
+ }
+}