Skip to content

Conversation

@rtripault
Copy link
Contributor

What does it do

It adds the ability to use a class implementing ArrayAccess interface to "forward" logs to.

Why is it needed

It provides the ability to "proxy" logs to a PSR/Monolog logger, ie.

use Monolog\Logger;
use Psr\Log\LoggerInterface;

final class Proxy implements \ArrayAccess
{
    private LoggerInterface $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    /**
     * @param mixed $offset
     * @param mixed $value
     */
    public function offsetSet($offset, $value): void
    {
        $this->logger->log(...self::modxLogEntryToMonolog($value));
    }

    /**
     * @param mixed $offset
     */
    public function offsetExists($offset): bool
    {
        return false;
    }

    /**
     * @param mixed $offset
     */
    public function offsetGet($offset): void
    {
        return;
    }

    /**
     * @param mixed $offset
     */
    public function offsetUnset($offset): void
    {
        return;
    }

    /**
     * Converts a modx produced log entry (using ARRAY_EXTENDED target) to monolog usable arguments
     *
     * @param array{
     *     'content': string,
     *     'level': string,
     *     'msg': string,
     *     'def': string,
     *     'file': string,
     *     'line': string
     * } $payload
     *
     * @see \xPDO::_log()
     *
     * @return array{int, string, array<mixed>}
     * @see LoggerInterface::log()
     */
    private static function modxLogEntryToMonolog(array $payload): array
    {
        \preg_match('/^\[([^\]]+)\].*/', $payload['content'], $matches);
        $datetime = $matches[1];

        $context = [
            'extra' => [
                'datetime' => $datetime,
                'level_name' => $payload['level'],
            ],
        ];

        // remove invalid characters from filename and linenumber (added by modx::log())
        $file = trim(str_replace('@ ', '', $payload['file']));
        $line = trim(str_replace(':', '', $payload['line']));

        // prepend MODX base path to index.php errors
        if ($file === '/index.php') {
            $file = MODX_BASE_PATH . $file;
        }

        // make sure the file exists
        if (file_exists($file)) {
            $context['extra']['fileName'] = $file;
            $context['extra']['lineNumber'] = $line;
        }

        return [self::getMonologLevel($payload['level']), $payload['msg'], $context];
    }

    /**
     * @param string $level
     *
     * @return int
     *
     * @see \xPDO::_getLogLevel()
     */
    private static function getMonologLevel(string $level): int
    {
        switch ($level) {
            case 'DEBUG':
                return Logger::DEBUG;
            case 'INFO':
                return Logger::INFO;
            case 'WARN':
                return Logger::WARNING;
            case 'ERROR':
                return Logger::ERROR;
            case 'FATAL':
            default:
                return Logger::EMERGENCY;
        }
    }
}

then once modX/XPDO is constructed (pseudo code)

/** @var \Psr\Log\LoggerInterface $logger */
$proxy = new Proxy($logger)
$modx->setLogTarget([
            'target' => 'ARRAY_EXTENDED',
            'options' => [
                'var' => & $proxy,
            ],
        ]);

Somehow related/alternative to #213

Hoping that makes sense and you feel it could be a valuable addition to the code.

@cla-bot
Copy link

cla-bot bot commented Sep 28, 2022

Thank you for your pull request and welcome to our community. We could not parse the GitHub identity of the following contributors: Romain Tripault.
This is most likely caused by a git client misconfiguration; please make sure to:

  1. check if your git client is configured with an email to sign commits git config --list | grep email
  2. If not, set it up using git config --global user.email email@example.com
  3. Make sure that the git commit email is configured in your GitHub account settings, see https://github.com/settings/emails

@Mark-H
Copy link
Contributor

Mark-H commented Sep 28, 2022

LGTM, but would be nice to work on PSR-3 in xPDO 3.2 or so too :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants