Ellrion
6/23/2016 - 9:20 AM

Multiple logging (pool of loggers) for Laravel

Multiple logging (pool of loggers) for Laravel

<?php namespace App\Services\Log;

use Illuminate\Support\Manager;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Psr\Log\LoggerInterface;
use Illuminate\Contracts\Logging\Log as LogContract;

class WritersPool extends Manager implements LogContract, LoggerInterface
{
    protected $defaultLoggerName;

    /**
     * Get the default driver name.
     *
     * @return string
     */
    public function getDefaultDriver()
    {
        return $this->defaultLoggerName;
    }

    /**
     * Set the default logger.
     *
     * @param string      $name
     * @param LogContract $writer
     *
     * @return string
     */
    public function setDefaultLogger($name, LogContract $writer)
    {
        $this->defaultLoggerName = $name;
        $this->drivers[$name] = $writer;
    }

    /**
     * Get a logger instance by name.
     *
     * @param string|null $logger
     *
     * @return mixed
     */
    public function logger($logger = null)
    {
        return $this->driver($logger);
    }

    /**
     * Register a file logger creator.
     *
     * @param $name
     * @param $path
     * @param string   $level
     * @param int|null $days
     */
    public function addFileLogger($name, $path, $level = 'debug', $days = null)
    {
        $this->extend($name, function () use ($name, $path, $level, $days) {
            $handler = null === $days
                ? new StreamHandler($path, $level)
                : new RotatingFileHandler($path, $days, $level);
            $handler->setFormatter(new LineFormatter(null, null, true, true));

            return new Logger($name, [$handler]);
        });
    }

    /**
     * System is unusable.
     *
     * @param string $message
     * @param array  $context
     *
     * @return null
     */
    public function emergency($message, array $context = [])
    {
        $this->logger()->emergency($message, $context);
    }

    /**
     * Log an alert message to the logs.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function alert($message, array $context = [])
    {
        $this->logger()->alert($message, $context);
    }

    /**
     * Log a critical message to the logs.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function critical($message, array $context = [])
    {
        $this->logger()->critical($message, $context);
    }

    /**
     * Log an error message to the logs.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function error($message, array $context = [])
    {
        $this->logger()->error($message, $context);
    }

    /**
     * Log a warning message to the logs.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function warning($message, array $context = [])
    {
        $this->logger()->warning($message, $context);
    }

    /**
     * Log a notice to the logs.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function notice($message, array $context = [])
    {
        $this->logger()->notice($message, $context);
    }

    /**
     * Log an informational message to the logs.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function info($message, array $context = [])
    {
        $this->logger()->info($message, $context);
    }

    /**
     * Log a debug message to the logs.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function debug($message, array $context = [])
    {
        $this->logger()->debug($message, $context);
    }

    /**
     * Log a message to the logs.
     *
     * @param string $level
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function log($level, $message, array $context = [])
    {
        $this->logger()->log($message, $context);
    }

    /**
     * Register a file log handler.
     *
     * @param string $path
     * @param string $level
     *
     * @return void
     */
    public function useFiles($path, $level = 'debug')
    {
        $this->logger()->useFiles($path, $level);
    }

    /**
     * Register a daily file log handler.
     *
     * @param string $path
     * @param int    $days
     * @param string $level
     *
     * @return void
     */
    public function useDailyFiles($path, $days = 0, $level = 'debug')
    {
        $this->logger()->useDailyFiles($path, $days, $level);
    }
}
<?php namespace App\Providers;

use App\Services\Log\WritersPool;
use Illuminate\Support\ServiceProvider;
use Monolog\Handler\RavenHandler;
use Psr\Log\LogLevel;

class LoggingServiceProvider extends ServiceProvider
{
    public function boot()
    {
    }

    /**
     * Перерегистрируем сервис логирования в тот который умеет работать с несколькими логерами.
     *
     */
    public function register()
    {
        $pool = new WritersPool($this->app);
        $this->registerDefaultLogger($pool);
        $this->registerOtherLoggers($pool);

        $this->app->instance('log', $pool);

        $this->configureHandlers();
    }

    /**
     * Установка главного логера, создаваемого фреймворком как логера по умолчанию.
     *
     * @param WritersPool $pool
     */
    private function registerDefaultLogger(WritersPool $pool)
    {
        $base_writer = $this->app->make('log');
        $pool->setDefaultLogger('laravel', $base_writer);
    }

    /**
     * Регистрация дополнительных логеров указанных в конфигурации.
     *
     * @param WritersPool $pool
     */
    private function registerOtherLoggers(WritersPool $pool)
    {
        $loggers = $this->app->make('config')->get('app.loggers', []);
        foreach ($loggers as $log => $config) {
            if (is_string($config)) {
                $config = ['file' => $config];
            }
            $pool->addFileLogger(
                $log,
                array_get($config, 'file'),
                array_get($config, 'level', $this->getBaseLogLevel()),
                array_get($config, 'days')
            );
        }
    }

    /**
     * Конфигурирование обработчиков логов.
     */
    protected function configureHandlers()
    {
      //можно добавить обработчики, например sentry
    }

    /**
     * Основной уровень логирования для логгеров у которых он не конкретезирован.
     */
    protected function getBaseLogLevel()
    {
        return $this->app->make('config')->get('app.debug') ? LogLevel::DEBUG : LogLevel::INFO;
    }

}