首页 文章

扩展Laravel核心日志记录

提问于
浏览
3

因为我在理解事情时遇到了问题,所以我回来时会遇到更多的Laravel问题 .

我再次尝试创建一个包来进行自己的日志记录 . 在做了一些额外的阅读并完成核心代码并尝试其他方法之后,我得出的结论是,我需要做的就是扩展laravel日志记录的核心功能,以便它记录到一个不同的路径自定义格式化程序

我已经创建了我的包 . 这是我的服务提供者类:

use Illuminate\Log\LogServiceProvider;

class VmlogServiceProvider extends LogServiceProvider {


    /**
     * Bootstrap the application events.
     *
     * @return void
     */
    public function boot()
    {
        App::bind('log', function()
        {
            return new Vm\Vmlog\Vmlog;
        });     
        parent::boot();

    }

}

?>

这是VmLog类

<?php namespace Vm\Vmlog;

use App;
use Illuminate\Support\ServiceProvider;
use Log;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\RotatingFileHandler;

class Vmlog extends \Illuminate\Log\Writer {


    protected $path;
    protected $formatter;
    protected $stream;
    protected $rotatingStream;

    public function __construct() {

        $output = APP_HOST."|%datetime%|%level%|%level_name%|".__METHOD__."|%message%|%context%".PHP_EOL;
        $this->path = VM_LOGPATH.APP_VLCODE."/".APP_VLCODE."_".APP_INSTANCE.".log";
        $this->formatter = new LineFormatter($output, $dateFormat);

        parent::__construct();
    }

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

        $this->stream = new StreamHandler($this->path, $level);
        $this->stream->setFormatter($this->formatter);

        $this->monolog->pushHandler($this->stream);
    }

    /**
     * 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')
    {
        $level = $this->parseLevel($level);
        $this->rotatingStream = new RotatingFileHandler($this->path, $days, $level);
        $this->rotatingStream->setFormatter($this->formatter);

        $this->monolog->pushHandler($this->rotatingStream);
    }

}

?>

我在app.php中注释掉了LogServiceProvider,并在我的VmlogServiceProvider中添加了它 .

然而,当我尝试运行时,我收到以下错误 .

调用未定义的方法Illuminate \ Support \ Facades \ Log :: useDailyFiles()

我不明白为什么会这样 . 我已经删除了核心LogServiceProvider,我已经添加了我自己的地方并按照文档(我认为)正确绑定了它 . 我在这做错了什么?

2 回答

  • 6

    为什么在服务提供商中使用Boot方法?

    替换Laravel的日志

    您可能打算在该服务提供商中使用register方法而不是 boot 方法?

    看起来您的实现将覆盖默认 Logger ,而不是创建其他日志 . 这是你的意图吗?在这种情况下,请注意您已使用 boot 方法注册"log"的实例,但是 register 方法正在重新执行该工作 . (也许用默认值替换它?我不确定会导致什么行为) .

    另外一个日志

    如果要添加其他日志,则无需扩展Laravel的服务提供商即可 .

    在新文件和您自己的命名空间内,创建一个 LogServiceProvider

    <?php namespace Fideloper\Log;
    
    use Illuminate\Support\ServiceProvider;
    
    class LogServiceProvider extends ServiceProvider {
    
        /**
         * Indicates if loading of the provider is deferred.
         *
         * @var bool
         */
        protected $defer = false;
    
        /**
         * Register the service provider.
         *
         * @return void
         */
        public function register()
        {
            $logger = new Writer(new \Monolog\Logger('my-custom-log'), $this->app['events']);
    
            $logFile = 'my-custom-log.txt';
    
            $logger->useDailyFiles(storage_path().'/logs/'.$logFile);
    
            $this->app->instance('fideloper.log', $logger);
    
            $this->app->bind('Fideloper\Log\Writer', function($app)
            {
                return $app->make('fideloper.log');
            });
        }
    
        /**
         * Get the services provided by the provider.
         *
         * @return array
         */
        public function provides()
        {
            return array('fideloper.log');
        }
    
    }
    

    然后创建一个新的日志编写器(类似于你的工作方式):

    <?php namespace Fideloper\Log;
    
    use Illuminate\Log\Writer as BaseWriter;
    
    class Writer extends BaseWriter {}
    

    请注意,我没有为我的扩展编写器类添加任何额外的功能,但我可以 .

    这个设置的 con 是我没有创建或覆盖 Log 外观来使用我的新 Logger . 对 Log::whatever() 的任何调用仍然会转到Laravel的默认值 . 我创建了一个新的 Fideloper\Log\Writer 对象,因为Laravel能够自动提供类依赖性 .

    $log = App::make('fideloper.log');
    
    // Or get auto-created by laravel by making it a dependency
    //   in a controller, for example:
    <?php
    
    use Fideloper\Log\Writer
    
    class SomeController extends BaseController {
    
        public function __construct(Writer $log)
        {
            $this->log = $log;
    
            //Later
            $this->log->error('SOME CUSTOM ERROR');
        }
    
    }
    
  • 1

    我已经设法将它全部排序,因此将为完整性提供答案 .

    我们基本上模仿了LogServiceProvider类,但是我们调用了自己的Vmlog类,而不是调用Laravel Writer类,只是扩展了writer类 . 这样,原始日志记录的所有功能都保持不变,我们只需覆盖我们需要的功能 . 您还需要注释Laravel Log服务提供程序的注册,并将您自己的注册表放在app.php文件中 .

    这是ServiceProvider类 .

    <?php namespace vm\Vmlog;
    
    use Monolog\Logger;
    use Illuminate\Log\LogServiceProvider;
    use Illuminate\Support\ServiceProvider;
    
    class VmlogServiceProvider extends LogServiceProvider {
    
        /**
         * Bootstrap the application events.
         *
         * @return void
         */
        public function boot()
        {
            $this->package('vm/vmlog');
        }
    
        /**
         * Register the service provider.
         *
         * @return void
         */
        public function register()
        {
            $logger = new Vmlog(new Logger('log'), $this->app['events']);
    
            $this->app->instance('log', $logger);
    
            if (isset($this->app['log.setup']))
            {
                call_user_func($this->app['log.setup'], $logger);
            }
        }
    }
    
    ?>
    

    这是扩展Writer类的Vmlog类 .

    <?php namespace vm\Vmlog;
    
    use Illuminate\Support\ServiceProvider;
    use Monolog\Formatter\LineFormatter;
    use Monolog\Handler\StreamHandler;
    use Monolog\Handler\RotatingFileHandler;
    use Illuminate\Events\Dispatcher;
    use Monolog\Logger as MonologLogger;
    
    
    class Vmlog extends \Illuminate\Log\Writer {
    
    
        protected $path;
        protected $dateFormat;
        protected $output;
    
        public function __construct(MonologLogger $monolog, Dispatcher $dispatcher = null) 
        {
            // Do stuff
            $this->dateFormat = 'Y-m-d\TH:i:s';
            $this->output = "|%datetime%|%level%|%level_name%|%message%|%context%".PHP_EOL;
    
            parent::__construct($monolog, $dispatcher);
        }
    
        /**
         * Register a file log handler.
         *
         * @param  string  $path
         * @param  string  $level
         * @return void
         */
        public function useFiles($path, $level = 'debug')
        {
            $level = $this->parseLevel($level);
            $this->path = VM_LOGPATH.APP_VLCODE."/".APP_VLCODE."_".APP_INSTANCE.".log";
            $formatter = new LineFormatter(APP_HOST.$this->output, $this->dateFormat);
            $stream = new StreamHandler($this->path, $level);
            $stream->setFormatter($formatter);
    
            $this->monolog->pushHandler($stream);
        }
    
        /**
         * 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')
        {
            $level = $this->parseLevel($level);
            $this->path = VM_LOGPATH.APP_VLCODE."/".APP_VLCODE."_".APP_INSTANCE.".log";
            $formatter = new LineFormatter(APP_HOST.$this->output, $this->dateFormat);
            $stream = new RotatingFileHandler($this->path, $days, $level);
            $stream->setFormatter($formatter);
    
            $this->monolog->pushHandler($stream);
        }
    
    }
    
    ?>
    

    我仍然需要这样做,以便在包的配置文件中配置日志路径,但是现在和此答案都可以 .

相关问题