扩展 Laravel 核心日志记录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20519960/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Extending Laravel core logging
提问by SynackSA
I'm back with more Laravel problems as I'm having a problem understanding things.
我回来了更多 Laravel 问题,因为我在理解事物时遇到了问题。
Again, I'm attempting to create a package to do my own logging. After doing some extra reading and going through the core code and trying other approaches, I've come to the conclusion that all I need to do is extend the core functionality of the logging of laravel, so that it logs to a different path with a custom formatter.
再次,我试图创建一个包来做我自己的日志记录。在做了一些额外的阅读和阅读核心代码并尝试其他方法之后,我得出的结论是,我需要做的就是扩展 laravel 日志记录的核心功能,以便它以不同的路径记录到自定义格式化程序。
I've created my package. Here is my service provider class:
我已经创建了我的包。这是我的服务提供者类:
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();
}
}
?>
Here's the VmLog class
这是 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);
}
}
?>
I've commented out the LogServiceProvider in app.php and added in my VmlogServiceProvider in it's place.
我已经注释掉了 app.php 中的 LogServiceProvider 并在它的位置添加了我的 VmlogServiceProvider。
Yet, when I try run things, I get the following error.
但是,当我尝试运行时,出现以下错误。
Call to undefined method Illuminate\Support\Facades\Log::useDailyFiles()
调用未定义的方法 Illuminate\Support\Facades\Log::useDailyFiles()
I don't understand why this is happening. I've removed the core LogServiceProvider, I've added my own in it's place and binded it correctly, as per the documentation (I think). What am I doing wrong here?
我不明白为什么会这样。我已经删除了核心 LogServiceProvider,我已经在它的位置添加了我自己的并正确绑定它,根据文档(我认为)。我在这里做错了什么?
回答by fideloper
Why are you using the Boot method in the service provider?
你为什么在服务提供者中使用 Boot 方法?
Replacing Laravel's log
替换 Laravel 的日志
You may have meant to use the register
method instead of the boot
method in that service provider?
您可能打算使用该register
方法而不是boot
该服务提供者中的方法?
It looks like your implementation of this will override the default logger, rather than create an additional log. Is that your intention? In that case, note that you have used the boot
method to register an instance of "log", but then the register
method is re-doing that work. (perhaps replacing it back with the default? I'm not sure what behavior would result).
看起来您的实现将覆盖默认记录器,而不是创建额外的日志。这是你的意图吗?在这种情况下,请注意您已使用该boot
方法注册了“log”的实例,但该register
方法正在重新执行该工作。(也许用默认值替换它?我不确定会导致什么行为)。
An additional log
额外的日志
If you want to add an additional log, you can do that without having to extend Laravel's service provider.
如果你想添加额外的日志,你可以做到这一点,而无需扩展 Laravel 的服务提供者。
Within a new file and your own namespace, create a LogServiceProvider
:
在一个新文件和您自己的命名空间中,创建一个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');
}
}
Then create a new log writer (similar to how you've done):
然后创建一个新的日志编写器(类似于您所做的):
<?php namespace Fideloper\Log;
use Illuminate\Log\Writer as BaseWriter;
class Writer extends BaseWriter {}
Note that I didn't add any extra functionality to my extended writer class, but I could.
请注意,我没有向扩展的 writer 类添加任何额外的功能,但我可以。
A conof this setup is that I haven't created or over-written the Log
facade to use my new logger. Any call to Log::whatever()
will still go to Laravel's default. I create a new Fideloper\Log\Writer
object and it works because of Laravel's ability to provide class dependencies automatically.
这种设置的一个缺点是我没有创建或覆盖Log
外观来使用我的新记录器。任何调用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');
}
}
回答by SynackSA
I've managed to get it all sorted, so will provide the answer for completeness sake.
我已经设法把它全部整理好了,所以为了完整起见,我会提供答案。
We basically mimic the LogServiceProvider class, but instead of calling the Laravel Writer class, we call out own Vmlog class, that simply extends the writer class. That way all functionality of the original logging is kept in place and we simply override the functions we need to. You also need to comment out the registration of the Laravel Log service provider and put your own one in the app.php file.
我们基本上模仿了 LogServiceProvider 类,但不是调用 Laravel Writer 类,而是调用自己的 Vmlog 类,它只是扩展了 writer 类。这样,原始日志的所有功能都保留在原位,我们只需覆盖我们需要的功能。还需要把Laravel Log服务提供者的注册注释掉,把自己的注册到app.php文件中。
Here is the ServiceProvider Class.
这是 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);
}
}
}
?>
Here is the Vmlog class that extends the Writer class.
这是扩展 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);
}
}
?>
I still need to make it so that the log path is configured in the config files for the package, but this will do for now and for this answer.
我仍然需要这样做,以便在包的配置文件中配置日志路径,但是现在和这个答案都可以。