Рубрики
Uncategorized

Lumen реализует мониторинг SQL

Автор оригинала: David Wong.

Мой блог

до Люмен Кадр из 5.6 Обновление до 5.7 。 найти laravel - sql -регистратор Пакет не может правильно войти в систему. Мы проверили и обнаружили, что Люмен Фреймворк не подходит DB Введите инъекцию событие Объект, в результате чего он не сможет нормально прослушивать SQL.

Так что решение очень простое.

// file: bootstrap/app.php
$app ["DB"] - > connection() - > seteventdispatcher ($app ["events"); // add this line before the registration below
$app->register(Mnabialek\LaravelSqlLogger\Providers\ServiceProvider::class);

Но это также заставило меня заинтересоваться тем, как реализовать ведение журнала SQL. Далее давайте подробнее узнаем о том, как реализовать мониторинг SQL.

Мы знаем, что Чудо Это очень просто. Вам нужны только следующие методы для мониторинга SQL:

namespace App\Providers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     *Start application service
     *
     * @return void
     */
    public function boot()
    {
        DB::listen(function ($query) {
            // $query->sql
            // $query->bindings
            // $query->time
        });
    }
    
    //...
}

Но в Lumen Нет возможности использовать этот метод. Lumen Есть несколько способов отладки SQL, но это не то, что нам нужно. Таким образом, мы можем только сами записывать события мониторинга.

Конкретное решение состоит в том, чтобы сначала создать файл прослушивателя.

// file: app\Listeners\QueryListener.php

namespace App\Listeners;

use Illuminate\Database\Events\QueryExecuted;

class QueryListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  ExampleEvent  $event
     * @return void
     */
    public function handle(QueryExecuted $event)
    {
        DD ($event); // print it directly here
    }
}

Затем мы зарегистрируем его напрямую

// file: app/Providers/EventServiceProvider.php
namespace App\Providers;

use App\Listeners\QueryListener;
use Illuminate\Database\Events\QueryExecuted;
use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        Queryexecuted:: class = > [// this line
            Querylistener:: class, // and this line
        ],
    ];
}

Не забудьте зарегистрироваться Поставщики услуг

// file: bootstrap/app.php'

/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application's service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/

// $app->register(App\Providers\AppServiceProvider::class);
// $app->register(App\Providers\AuthServiceProvider::class);
$app - > register (APP \ providers \ eventserviceprovider:: class); // uncomment this line

Далее идет практика. Сначала мы создаем контроллер

//file: app/Http/Controllers/UserController.php
namespace App\Http\Controllers;

use App\User;

class UserController extends Controller
{
    public function one() {
        Return user:: where ("Id", 1) - > first(); // execute the query method in the controller
    }
}

Маршрут регистрации

// file: routes/web.php
$router - > get ('/ one', "usercontroller @ one"); // define access routes

Наконец, не забудьте включить функцию БД и заполнить конфигурацию базы данных (все обязательно это сделают, поэтому я не буду публиковать код).

Давайте попробуем запустить его:

QueryExecuted {#65 ▼
  +sql: "select * from `users` where `id` = ? limit 1"
  +bindings: array:1 [▶]
  +time: 2.06
  +connection: MySqlConnection {#66 ▶}
  +connectionName: "mysql"
}

Открытие оказалось успешным. Затем вы можете выполнить ведение журнала.

Давайте изменим код следующим образом:

// file: app/Listeners/QueryListener.php
namespace App\Listeners;

use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Support\Facades\Log;

class QueryListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  ExampleEvent  $event
     * @return void
     */
    public function handle(QueryExecuted $event)
    {
        $query = $event - > SQL; // get SQL statement
        foreach ($event->bindings as $bind) {
            $query = preg_replace ('/ \? /', (is_numeric ($bind)? $bind: '\' '. $bind.' \ ', $query, 1); // replace the value in SQL with the actual value
        }
        Log:: info ("query: {$query} time: {$event - > time} MS"); // print SQL and execution time to the log
    }
}

Хотя ведение журнала SQL было реализовано, это не то, что нам нужно, потому что журналы SQL и ошибок собраны вместе. Это трудно прочесть. Затем мне нужно поместить его в отдельный файл.

// file: app/Listeners/QueryListener.php
namespace App\Listeners;

use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Http\Request;

class QueryListener
{
    /**
     *File path written
     * @var string
     */
    protected $writeFile;

    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        $this - > WriteFile = storage path(). Directory separator. "Logs". Directory separator. "SQL -" date ("YMD") ". Log"; // define the output log path
    }

    /**
     * Handle the event.
     *
     * @param  QueryExecuted  $event
     * @param Request $request
     * @return void
     */
    public function handle(QueryExecuted $event)
    {
        $query = $event->sql;
        foreach ($event->bindings as $bind) {
            $query = preg_replace('/\?/', (is_numeric($bind) ? $bind : '\'' . $bind . '\''), $query, 1);
        }

        File put contents ($this - > WriteFile, "query: {$query} time: {$event - > time} MS", file put); // directly use file put contents to input the content. And note that if file file append is not added, it will become overwrite. The function of this constant is to append and write files.
    }
}

Далее мы продолжим совершенствоваться, то есть в настоящее время мы печатаем во всех средах, но нам нужно только выполнить отладку в среде разработки. Таким образом, мы можем внести следующие изменения:

// file: app/Providers/EventServiceProvider.php
namespace App\Providers;

use App\Listeners\QueryListener;
use Illuminate\Database\Events\QueryExecuted;
use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [];

    public function register()
    {
        If (env ("app" env ") = =" local ") {// judge the environment
            $events = app('events');

            $events - > Listen (queryexecuted:: class, querylistener:: class); // register the listener manually
        }
    }
}

Затем реализуется функция мониторинга SQL.

на самом деле laravel-sql-регистратор Есть также некоторые расширенные функции отображения. Например, при печати журнала вместе с ним будет напечатан URL-адрес запроса. Время запроса на печать и т.д. Я не хочу их улучшать. Если вам интересно, вы можете сделать это сами. Это очень просто.