【问题标题】:Laravel 7 set log path dynamically in Job classLaravel 7 在 Job 类中动态设置日志路径
【发布时间】:2020-04-04 13:46:35
【问题描述】:

我在 Laravel 7.3 上构建项目,同时运行多个作业。 我需要让每个 Job 将日志写入不同的每日旋转文件。日志文件的名称应基于 Job 正在处理的模型。

问题是我找不到聪明的解决方案。

我尝试过的:

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) 对config/logging.php 中的通道使​​用tap 参数。

Example in laravel docs 不知道如何将模型名称传递给 CustomizeFormatter 来设置文件名。

我几乎可以肯定有聪明的解决方案,我只是错过了一些东西。 有什么建议吗?谢谢!

【问题讨论】:

    标签: php laravel laravel-7 laravel-jobs


    【解决方案1】:

    您可以继承日志管理器以允许动态配置

    <?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);
            });
        }
    }
    

    编辑:我刚刚看到 config/app.php 中缺少 Laravel 的日志服务提供程序,这是因为它是由应用程序“硬加载”的。您仍然可以通过继承应用程序本身来替换它

    <?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

    $baseConfig['path'] = $model + '.log';
    

    【讨论】:

    • 感谢您的解决方案。它可以工作,但是在测试时遇到了奇怪的问题。创建新的空控制器并使用 1) Log::info('test'); 进行测试2) app('log')->channel('myconfigname:testmodel')->info('test');两个测试都导致错误 Undefined offset: 1 in LogManager (explode string)。有什么想法吗?静态 Log::info() 使用相同的 LogManager 不是很奇怪吗?
    • 是的,我的代码示例只有在频道名称中有 : 时才有效,我编辑了它,它现在应该可以工作了 :)
    • 很高兴,我遇到了关于数据库和文件系统的同样问题;)
    【解决方案2】:

    我有一个自 Laravel 4 以来一直在使用的解决方案,虽然它不遵循“Laravel”的做事方式。

    class UserTrackLogger
    {
        /**
         * @var $full_path string
         */
        protected $full_path;
        /**
         * @var $tenant string
         */
        protected $tenant;
        /**
         * @var $user User
         */
        protected $user;
        /**
         * @var $request Request
         */
        protected $request;
    
        public static function log(string $message, Request $request, User $user, array $data = []): void
        {
            /** @noinspection PhpVariableNamingConventionInspection */
            $userTrack = new static($request, $user);
            $userTrack->write($message, $data);
        }
    
        protected function __construct(Request $request, User $user)
        {
            $this->request = $request;
            $this->user = $user;
            $this->tenant = app()->make('tenant')->tenant__name;
            $path = storage_path() . "/logs/{$this->tenant}/users";
    
            $filename = $this->user->username_with_name;
            $this->full_path = Formatter::formatPath("{$path}/{$filename}.log");
            self::makeFolder($this->full_path);
        }
    
        protected function write(string $message, array $data = []): void
        {
            $formatter = $this->getFormat();
            $record = [
                'message'    => $message,
                'context'    => $data,
                'extra'      => [],
                'datetime'   => date(Utility::DATETIME_FORMAT_DEFAULT),
                'level_name' => 'TRACK',
                'channel'    => '',
            ];
            file_put_contents($this->full_path, $formatter->format($record), FILE_APPEND);
        }
    
        protected function getFormat(): FormatterInterface
        {
            $ip = $this->request->getClientIp();
            $method = strtoupper($this->request->method());
            $format = "[%datetime%][{$this->tenant}][{$this->user->username}][{$this->user->name}]: $ip $method %message% %context%\n";
            return new LineFormatter($format, null, true);
        }
    
        protected static function makeFolder(string $full_path): bool
        {
            $path = dirname($full_path);
            if ( !is_dir($path) ) {
                return mkdir($path, 0755, true);
            }
    
            return false;
        }
    }
    

    当我想记录一些东西时,我会做UserTrackLogger::log($request-&gt;fullUrl(), $request, $user, $data);

    我的建议是创建一个与此类似但扩展 RotatingFileHandler 的记录器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 2021-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多