使用 Monolog\Handler\BrowserConsoleHandler 进行 Laravel 日志记录

cod*_*elk 5 php logging laravel monolog laravel-5

如何Laravel 5的记录改成Monolog\Handler\BrowserConsoleHandler

什么不会在Laravel 5工作,但确实在一个独立的PHP文件的工作:

use Illuminate\Support\Facades\Log;    
use Monolog\Handler\BrowserConsoleHandler;
use Monolog\Logger;

// create a log channel
$log = Log::getMonolog();
// $log = new Logger('Testlogger'); //doesn't make any difference
$log->pushHandler(new BrowserConsoleHandler(\Psr\Log\LogLevel::INFO));

// add records to the log
$log->addWarning('Foo');
$log->addError('Bar');
Run Code Online (Sandbox Code Playgroud)

所发生的一切是我的日志出现在日志文件中,但没有找到到浏览器的方式。如果我在没有框架的单个 PHP 文件中尝试代码,它可以工作,所以我认为这是 Laravel 问题。

我让它在安装 Firebug 和 FirePHP 的情况下工作,而$log->pushHandler(new FirePHPHandler());不是BrowserConsoleHandler但这不是解决方案,因为它发送带有标头的日志,但是当记录器想要发送标头时,我已经发送了一些调试回声。
BrowserConsoleHandler另一方面,在网站末尾添加了一个 JavaScript 片段,它完全符合我的需求。

那么,有没有人成功地添加BrowserConsoleHandler到 Laravel 的日志中?如何?

cod*_*elk 4

在阅读了大量源代码并让 xdebug 工作后,我终于弄清楚了:

BrowserConsoleHandler发送完成 php 脚本后截取的脚本register_shutdown_function()。此时,Laravel 已经向浏览器发送了完整的响应。因此,从生成的脚本中截取的脚本BrowseConsoleHandler从未发送到浏览器。

作为解决方法,您可以构建自己的Middlewarehttp://laravel.com/docs/5.0/middleware),手动调用代码生成并在发送之前将其添加到响应中。

创建app/Http/Middleware/LogBrowserConsole.php

<?php
namespace App\Http\Middleware;

use Illuminate\Contracts\Routing\Middleware;
use Illuminate\Support\Facades\Log;
use Monolog\Handler\BrowserConsoleHandler;

class LogBrowserConsole implements Middleware {

  public function handle($request, \Closure $next)
  {
    // add BrowserConsoleHandler to Laravel's Logger
    $log = Log::getMonolog();
    $log->pushHandler(new BrowserConsoleHandler(\Psr\Log\LogLevel::INFO));

    // invokes all your stuff like it would do without the middleware but with the new logger
    $response = $next($request);

    // after the request is done we care about the log entries
    $handlers = $log->getHandlers();

    $scriptSnippet = "";
    foreach($handlers as $handler){ // only handle BrowserConsoleHandler
        if($handler instanceof BrowserConsoleHandler){
            ob_start(); //start output buffer so we can save echo to variable
            $handler->send(); // create the scriptSnipped
            $scriptSnippet .= ob_get_clean();
        }
    }

    // write scriptSnippet to end of response content
    $content = $response->getContent();
    $response->setContent($content.$scriptSnippet);

    return $response;
  }
}
Run Code Online (Sandbox Code Playgroud)

在app/Http/Kernel.php中注册中间件:

protected $routeMiddleware = [
    'log.browserconsole' => 'App\Http\Middleware\LogBrowserConsole'
];
Run Code Online (Sandbox Code Playgroud)

并使用app/Http/routes.php中的中间件调用您的控制器:

Route::get('test', ['middleware' => 'log.browserconsole', 'uses'=>'TestController@test']);
Run Code Online (Sandbox Code Playgroud)

或者,如果您想对每个请求使用,Middleware您可以将其添加到

protected $middleware = [
'App\Http\Middleware\LogBrowserConsole'
];
Run Code Online (Sandbox Code Playgroud)

app/Http/Kernel.php中。

你的路线看起来像Route::get('test', 'TestController@test');


现在,您的Log::debug()等消息将被发送到日志文件(默认的 LogHandler 仍然可用,您刚刚添加了另一个),并且从中截取的脚本将BrowserConsoleHandler被构建并与所有日志项一起发送到浏览器。

请记住,最终要更改app/Http/Middleware/LogBrowserConsole\Psr\LogLevel::INFO中的日志级别以满足您的需求。