Язык: PHP
Framework: Laravel
Демо: http://laravel.jobtools.ru
Исходники: https://bitbucket.org/gerz/laravel.jobtools.ru/src/master/
Поставим задачу: нам нужен простой логгер сохраняющий все обращения к нашему серверу. Для удобства просмотра через WEB интерфейс всех, кто нас посетил, пусть данные будут сохранятся в таблицу MySQL. И пусть будет возможность отключения логгирования в конфиг файле.
Для начала опишем миграцию для создания нашей таблицы логов, для этого в консоли набираем artisan команду:
php artisan make:migration create_logs_table
Редактируем создавшийся файл миграции, который, кстати, по умолчанию создается по следующему пути: \database\migrations\2019_06_04_133003_create_logs_table.php
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateLogTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('logs', function (Blueprint $table) { $table->bigIncrements('id'); $table->dateTime('time'); $table->integer('duration'); $table->string('ip',100)->nullabe(); $table->string('url')->nullabe(); $table->string('method',10)->nullabe(); $table->string('input')->nullabe(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('logs'); } }
Мы определили поля, необходимые для нашего логера:
- time — время события;
- duration — длительность;
- ip — ip адрес зашедшего пользователя;
- url — адрес, который запросил пользователь;
- method — HTTP метод (GET, POST);
- input — передаваемые параметры.
Создадим таблицу по нашей миграции:
php artisan migrate
Таблица создана, приступаем к созданию middleware — фильтр обработки HTTP-запросов. Советую ознакомится с документацией Что такое Middleware. На помощь нам опять придет artisan:
php artisan make:middleware DataLogger
Допишем в созданный по пути \app\Http\Middleware\DataLogger.php файл следующий код:
<?php namespace App\Http\Middleware; use Closure; use App\Models\Log; //Прописываем нашу модель, для возможности доступа к ней class DataLogger { private $startTime; //Сохраним в дальнейшем в этой переменной время начала запроса, для просчета общей длительности запроса /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) //Функция в которую приходи наш запрос { $this->startTime = microtime(true); return $next($request); } public function terminate($request, $response) //Функция, которая вызывается после посылки ответа пользователю { if ( env('API_DATALOGGER', true) ) { //Если в env файле прописана опция API_DATALOGGER = true используем логирование if ( env('API_DATALOGGER_USE_DB', true) ) { // Если в env файле прописана опция API_DATA_LOGGER_USE_DB=true, то для сохранения используем БД иначе пишем просто в файл $endTime = microtime(true); $log = new Log(); $log->time = gmdate('Y-m-d H:i:s'); $log->duration = number_format($endTime - LARAVEL_START, 3); $log->ip = $request->ip(); $log->url = $request->fullUrl(); $log->method = $request->method(); $log->input = $request->getContent(); $log->save(); //Сохранили в базу нашу запись } else //Если опция записи в БД недоступна пишем в файл { $endTime = microtime(true); $filename = 'api_datalogger_' . date('d-m-y') . '.log'; $dataToLog = 'Time: ' . gmdate("F j, Y, g:i a") . "\n"; $dataToLog .= 'Duration: ' . number_format($endTime - LARAVEL_START, 3) . "\n"; $dataToLog .= 'IP Address: ' . $request->ip() . "\n"; $dataToLog .= 'URL: ' . $request->fullUrl() . "\n"; $dataToLog .= 'Method: ' . $request->method() . "\n"; $dataToLog .= 'Input: ' . $request->getContent() . "\n"; \File::append( storage_path('logs' . DIRECTORY_SEPARATOR . $filename), $dataToLog . "\n" . str_repeat("=", 20) . "\n\n"); //Записали в файл } } } }
В приведенном выше примере, все достаточно просто и прозрачно. При поступлении запроса в наш фильтр (функция Handle) сохраняем время начала запроса. После ответа пользователю в браузер, вызывается ‘завершающая процедура’ terminate, которая в зависимости от параметров в лог файле записывает данный в БД или файл.
Если сейчас запустить сервер и открыть любую страницу нашего приложения, то ничего не произойдет, не будет ни ошибки, ни записи логов. Нужно завершить создание middleware, зарегистрировав его в app\Http\Kernel.php
Допишите в переменной $middleware наш класс (он последний в списке):
protected $middleware = [ \App\Http\Middleware\CheckForMaintenanceMode::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, \App\Http\Middleware\TrustProxies::class, \App\Http\Middleware\DataLogger::class, ];
Наш фильтр будет вызываться при каждом запросе к серверу.
В следующей части создадим контроллер и шаблон для просмотра наших логов, хранящихся в базе данных.
В поле duration может возникнуть ошибка, т.к. число вероятнее будет дробным.
$table->integer(‘duration’);
Как добавить новое поле?
А где продожение?