Laravel 7 динамически устанавливать путь к журналу в классе Job - PullRequest
1 голос
/ 04 апреля 2020

Я строю проект на Laravel 7.3 с несколькими заданиями, которые выполняются одновременно. Мне нужно, чтобы каждое задание записывало логи в разные ежедневные файлы. Имя файла журнала должно основываться на модели, которую обрабатывает задание.

Проблема в том, что я не могу найти интеллектуальное решение.

Что я пробовал:

1 ) создание нескольких каналов в config/logging.php.

Это работает, как и ожидалось, но на данный момент существует около 50 различных рабочих мест, и количество продолжает расти. Метод уродлив и почти не поддерживается.

2) настройка Config(['logging.channels.CUSTOMCHANNEL.path' => storage_path('logs/platform/'.$this->platform->name.'.log')]);.

Использование переменной Config было плохой идеей, поскольку многие задания выполнялись один раз. В результате сообщения от одного задания часто записывались в другой журнал заданий.

3) с использованием Log::useDailyFiles()

Похоже, что это перестает работать с laravel 5.5 или 5.6. Просто получаю ошибку Call to undefined method Monolog\Logger::useDailyFiles(). Есть мысли, как сделать с работой в laravel 7?

4) используя параметр tap для канала в config/logging.php.

Пример в laravel документы Нет идей, как передать имя модели в CustomizeFormatter для настройки имени файла.

Я почти уверен, что есть разумное решение, и я просто что-то упустил. Кто-нибудь предлагает? Спасибо!

1 Ответ

1 голос
/ 04 апреля 2020

Вы можете унаследовать диспетчер журналов, чтобы разрешить динамическую c конфигурацию

<?php

namespace App\Log;

use Illuminate\Support\Str;
use Illuminate\Log\LogManager as BaseLogManager;

class LogManager extends BaseLogManager
{
    /**
     * Get the log connection configuration.
     *
     * @param  string  $name
     * @return array
     */
    protected function configurationFor($name)
    {
        if (!Str::contains($name, ':')) {
            return parent::configurationFor($name);
        }
        [$baseName, $model] = explode(':', $name, 2);
        $baseConfig = parent::configurationFor($baseName);
        $baseConfig['path'] = ...; //your logic
        return $baseConfig;
    }
}

Аналогично для Laravel поставщика услуг журналов, за исключением того, что его можно полностью заменить

<?php

namespace App\Log;

use Illuminate\Support\ServiceProvider;

class LogServiceProvider extends ServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('log', function ($app) {
            return new LogManager($app);
        });
    }
}

РЕДАКТИРОВАТЬ: я только что видел, что Laravel поставщик службы журналов отсутствует в config/app.php, это потому, что он "загружен" приложением. Вы по-прежнему можете заменить его, унаследовав само приложение

<?php

namespace App\Foundation;

use App\Log\LogServiceProvider;
use Illuminate\Events\EventServiceProvider;
use Illuminate\Routing\RoutingServiceProvider;
use Illuminate\Foundation\Application as BaseApplication;

class Application extends BaseApplication
{
    /**
     * Register all of the base service providers.
     *
     * @return void
     */
    protected function registerBaseServiceProviders()
    {
        $this->register(new EventServiceProvider($this));
        $this->register(new LogServiceProvider($this));
        $this->register(new RoutingServiceProvider($this));
    }
}

И, наконец, в bootstrap/app.php замените Illuminate\Foundation\Application на App\Foundation\Application

Например, если вы попробуете это

app('log')->channel('single:users')->debug('test');

Laravel будет использовать конфигурацию канала single и записывать в users.log, если ваше разрешение logi c равно

$baseConfig['path'] = $model + '.log';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...