FEATURE: add simple view for requests and queries
This commit is contained in:
@@ -71,7 +71,7 @@ class Settings extends Controller
|
|||||||
|
|
||||||
// set value and save or delete
|
// set value and save or delete
|
||||||
$setting->value = $value;
|
$setting->value = $value;
|
||||||
empty($value) ? $setting->delete() : $setting->save();
|
$setting->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()
|
return redirect()
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ return [
|
|||||||
'translatedName' => 'profiler::module.name',
|
'translatedName' => 'profiler::module.name',
|
||||||
'translatedDescription' => 'profiler::module.description',
|
'translatedDescription' => 'profiler::module.description',
|
||||||
'alias' => 'profiler',
|
'alias' => 'profiler',
|
||||||
'handler' => \Modules\Blog\Article\Handlers\Article::class,
|
'handler' => \Modules\Profiler\Handlers\ProfileHandler::class,
|
||||||
'providers' => [\Modules\Blog\Article\Providers\ArticleServiceProvider::class],
|
'providers' => [\Modules\Profiler\Providers\ProfilerServiceProvider::class],
|
||||||
'files' => ['start.php'],
|
'files' => ['start.php'],
|
||||||
'order' => 0,
|
'order' => -100,
|
||||||
];
|
];
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class UpdateHttpLogAddLoadAvg extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('http_log', function (Blueprint $table) {
|
||||||
|
$table->double('load_1')->nullable();
|
||||||
|
$table->double('load_5')->nullable();
|
||||||
|
$table->double('load_15')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('http_log', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('load_1');
|
||||||
|
$table->dropColumn('load_5');
|
||||||
|
$table->dropColumn('load_15');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class UpdateQueryLogAddRequestId extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('queries_log', function (Blueprint $table) {
|
||||||
|
$table->integer('http_log_id')
|
||||||
|
->nullable()
|
||||||
|
->unsigned()
|
||||||
|
->after('id')
|
||||||
|
->comment('FK to http_log');
|
||||||
|
|
||||||
|
$table->foreign('http_log_id')
|
||||||
|
->references('id')
|
||||||
|
->on('http_log')
|
||||||
|
->onDelete('cascade')
|
||||||
|
->onUpdate('cascade');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('queries_log', function (Blueprint $table) {
|
||||||
|
|
||||||
|
// $table->dropForeign('');
|
||||||
|
$table->dropColumn('http_log_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,14 @@ class HttpLog extends Model
|
|||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'method',
|
'method',
|
||||||
'url',
|
'url',
|
||||||
'time'
|
'time',
|
||||||
|
'load_1',
|
||||||
|
'load_5',
|
||||||
|
'load_15'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function queries()
|
||||||
|
{
|
||||||
|
return $this->hasMany(QueryLog::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,9 +9,15 @@ class QueryLog extends Model
|
|||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'query',
|
'query',
|
||||||
'bindings',
|
'bindings',
|
||||||
'time'
|
'time',
|
||||||
|
'http_log_id'
|
||||||
];
|
];
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'bindings' => 'array'
|
'bindings' => 'array'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function httpLog()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(HttpLog::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
namespace Modules\Profiler\Handlers;
|
||||||
|
|
||||||
|
use App\CMS\Contracts\Modules\BaseModuleHandler;
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
class ProfileHandler implements BaseModuleHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register admin menu (or multiple ones)
|
||||||
|
*
|
||||||
|
* This cannot be in ServiceProvider because Session is started at middleware. And ServiceProvider is called before
|
||||||
|
* starting any middleware..
|
||||||
|
*
|
||||||
|
* @param User $user model of logged user
|
||||||
|
*/
|
||||||
|
public static function registerAdminMenu(User $user)
|
||||||
|
{
|
||||||
|
// register links in admin menu
|
||||||
|
$menu = \Menu::instance('mainMenu');
|
||||||
|
|
||||||
|
$submenu = $menu->whereTitle(trans('admin/mainMenu.system'));
|
||||||
|
$submenu->route('profiler.index', trans('profiler::module.name'), [], 10, ['icon' => 'fa fa-dashboard']);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
<?php namespace Modules\Profiler\Http\Controllers;
|
<?php namespace Modules\Profiler\Http\Controllers;
|
||||||
|
|
||||||
use Pingpong\Modules\Routing\Controller;
|
use App\Http\Controllers\Admin\Controller;
|
||||||
|
use Modules\Profiler\Entities\HttpLog;
|
||||||
|
|
||||||
class ProfilerController extends Controller {
|
class ProfilerController extends Controller
|
||||||
|
{
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
return view('profiler::index');
|
$httpLog = HttpLog::orderBy('created_at', 'DESC')
|
||||||
}
|
->with('queries')
|
||||||
|
->paginate(25);
|
||||||
|
|
||||||
|
return view('profiler::index', compact('httpLog'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
namespace Modules\Profiler\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Admin\Controller;
|
||||||
|
use Modules\Profiler\Entities\HttpLog;
|
||||||
|
|
||||||
|
class QueryController extends Controller {
|
||||||
|
public function index(HttpLog $httpLog) {
|
||||||
|
$queries = $httpLog->queries;
|
||||||
|
|
||||||
|
return view('profiler::queries.index', compact('queries'));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
Route::group([
|
||||||
|
'prefix' => LaravelLocalization::setLocale(),
|
||||||
|
'namespace' => 'Modules\Profiler\Http\Controllers'
|
||||||
|
], function () {
|
||||||
|
Route::group([
|
||||||
|
'middleware' => ['admin'],
|
||||||
|
'prefix' => 'profiler'
|
||||||
|
], function () {
|
||||||
|
|
||||||
Route::group(['middleware' => 'web', 'prefix' => 'profiler', 'namespace' => 'Modules\Profiler\Http\Controllers'], function()
|
Route::get('/', 'ProfilerController@index')->name('profiler.index');
|
||||||
{
|
Route::get('{httpLog}/queries', 'QueryController@index')->name('queries.index');
|
||||||
Route::get('/', 'ProfilerController@index');
|
});
|
||||||
});
|
});
|
||||||
@@ -7,6 +7,8 @@ use Modules\Profiler\Entities\QueryLog;
|
|||||||
|
|
||||||
class Profiler
|
class Profiler
|
||||||
{
|
{
|
||||||
|
private $queries = [];
|
||||||
|
|
||||||
public function handle(Request $request, $next)
|
public function handle(Request $request, $next)
|
||||||
{
|
{
|
||||||
\DB::enableQueryLog();
|
\DB::enableQueryLog();
|
||||||
@@ -15,28 +17,47 @@ class Profiler
|
|||||||
|
|
||||||
public function terminate(Request $request, $response)
|
public function terminate(Request $request, $response)
|
||||||
{
|
{
|
||||||
$this->logRequest($request);
|
$this->queries = \DB::getQueryLog();
|
||||||
$this->logQueries();
|
|
||||||
|
$requestId = $this->logRequest($request);
|
||||||
|
$this->logQueries($requestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
protected function logRequest(Request $request)
|
protected function logRequest(Request $request)
|
||||||
{
|
{
|
||||||
$url = $request->fullUrl();
|
$url = $request->fullUrl();
|
||||||
$method = $request->getMethod();
|
$method = $request->getMethod();
|
||||||
$time = (microtime(true) - LARAVEL_START) * 1000;
|
$time = (microtime(true) - LARAVEL_START) * 1000;
|
||||||
|
|
||||||
HttpLog::create(['url' => $url, 'method' => $method, 'time' => $time]);
|
$data = ['url' => $url, 'method' => $method, 'time' => $time];
|
||||||
|
|
||||||
|
if (function_exists('sys_getloadavg')) {
|
||||||
|
$load = sys_getloadavg();
|
||||||
|
$data['load_1'] = $load[0];
|
||||||
|
$data['load_5'] = $load[1];
|
||||||
|
$data['load_15'] = $load[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
$http = HttpLog::create($data);
|
||||||
|
|
||||||
|
return $http->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function logQueries()
|
protected function logQueries($httpLogId = null)
|
||||||
{
|
{
|
||||||
$queries = \DB::getQueryLog();
|
foreach ($this->queries as $query) {
|
||||||
|
|
||||||
foreach ($queries as $query) {
|
|
||||||
QueryLog::create([
|
QueryLog::create([
|
||||||
'query' => $query['query'],
|
'query' => $query['query'],
|
||||||
'bindings' => $query['bindings'],
|
'bindings' => $query['bindings'],
|
||||||
'time' => $query['time']
|
'time' => $query['time'],
|
||||||
|
'http_log_id' => $httpLogId
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ class ProfilerServiceProvider extends ModuleServiceProvider
|
|||||||
$this->alias = 'profiler';
|
$this->alias = 'profiler';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boot the application events.
|
* Boot the application events.
|
||||||
*
|
*
|
||||||
@@ -28,10 +27,20 @@ class ProfilerServiceProvider extends ModuleServiceProvider
|
|||||||
{
|
{
|
||||||
parent::register();
|
parent::register();
|
||||||
|
|
||||||
$this->app['router']->prependMiddlewareToGroup('web', Profiler::class);
|
// register settings form
|
||||||
// $this->app['router']->prependMiddlewareToGroup('admin', Profiler::class);
|
$registrator = $this->app->make('registerSettingsExtension');
|
||||||
}
|
$registrator->register('profiler', 'profiler::module.name', 'profiler::settings.profiler');
|
||||||
|
|
||||||
|
// turn on profiler for visitor area (middleware group "web")
|
||||||
|
if (setting('useProfilerInVisitorArea', true)) {
|
||||||
|
$this->app['router']->prependMiddlewareToGroup('web', Profiler::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// use profiler also in admin?
|
||||||
|
if (setting('useProfilerInAdmin', true)) {
|
||||||
|
$this->app['router']->prependMiddlewareToGroup('admin', Profiler::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function setModulePath()
|
protected function setModulePath()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'name' => 'Profiler',
|
||||||
|
'index' => [
|
||||||
|
'createdAt' => 'Datum',
|
||||||
|
'httpMethod' => 'HTTP metoda',
|
||||||
|
'url' => 'URL',
|
||||||
|
'time' => 'Čas',
|
||||||
|
'systemLoad' => 'Load serveru'
|
||||||
|
],
|
||||||
|
'settings' => [
|
||||||
|
'useProfilerInVisitorArea' => 'Zapnout měření ve veřejné části?',
|
||||||
|
'useProfilerInAdmin' => 'Zapnout měření v administraci?'
|
||||||
|
]
|
||||||
|
];
|
||||||
@@ -1,11 +1,37 @@
|
|||||||
@extends('profiler::layouts.master')
|
@extends('admin.layoutWithNavigation')
|
||||||
|
|
||||||
|
@section('pageHeading', trans('profiler::module.name'))
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
|
||||||
<h1>Hello World</h1>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This view is loaded from module: {!! config('profiler.name') !!}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
<table class="table stripped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>@lang('profiler::module.index.createdAt')</td>
|
||||||
|
<td>@lang('profiler::module.index.httpMethod')</td>
|
||||||
|
<td>@lang('profiler::module.index.url')</td>
|
||||||
|
<td>@lang('profiler::module.index.time')</td>
|
||||||
|
<td>@lang('profiler::module.index.systemLoad')</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
|
||||||
|
@foreach($httpLog as $request)
|
||||||
|
<tr>
|
||||||
|
<td>{{$request->created_at->format('d.m.Y G:i')}}</td>
|
||||||
|
<td>{{$request->method}}</td>
|
||||||
|
<td>{{$request->url}}</td>
|
||||||
|
<td>{{number_format($request->time, 3)}} ms</td>
|
||||||
|
<td>{{$request->load_1}}, {{$request->load_5}}, {{$request->load_15}}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{route('queries.index', ['httpLog' => $request])}}">SQL</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{!! $httpLog->render() !!}
|
||||||
@stop
|
@stop
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Module Profiler</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
@yield('content')
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
@extends('admin.layoutWithNavigation')
|
||||||
|
|
||||||
|
@section('pageHeading', trans('profiler::module.name'))
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<table class="table stripped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>@lang('profiler::module.queries.createdAt')</td>
|
||||||
|
<td>@lang('profiler::module.queries.sql')</td>
|
||||||
|
<td>@lang('profiler::module.queries.binding')</td>
|
||||||
|
<td>@lang('profiler::module.queries.time')</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
|
||||||
|
@foreach($queries as $query)
|
||||||
|
<tr>
|
||||||
|
<td>{{$query->created_at->format('d.m.Y G:i')}}</td>
|
||||||
|
<td>{{$query->query}}</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
{{var_export($query->bindings)}}
|
||||||
|
</td>
|
||||||
|
<td>{{number_format($query->time, 3)}} ms</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
@endsection
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-9">
|
||||||
|
|
||||||
|
@php $profileVisitorArea = old('useProfilerInVisitorArea', isset($settings->useProfilerInVisitorArea) ? $settings->useProfilerInVisitorArea['val'] : null); @endphp
|
||||||
|
|
||||||
|
<span class="control-label">@lang('profiler::module.settings.useProfilerInVisitorArea')</span>
|
||||||
|
<label>
|
||||||
|
<input class="radio" type="radio" name="useProfilerInVisitorArea"
|
||||||
|
value="1"
|
||||||
|
@if($profileVisitorArea === "1") checked @endif />
|
||||||
|
<span>@lang('common.yes')</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input class="radio" type="radio" name="useProfilerInVisitorArea"
|
||||||
|
value="0"
|
||||||
|
@if($profileVisitorArea === "0") checked @endif />
|
||||||
|
<span>@lang('common.no')</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
@include('admin.settings.snippets.commonSettings', ['field' => 'useProfilerInVisitorArea'])
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-9">
|
||||||
|
@php $profileAdmin = old('useProfilerInAdmin', isset($settings->useProfilerInAdmin) ? $settings->useProfilerInAdmin['val'] : false); @endphp
|
||||||
|
<span class="control-label">@lang('profiler::module.settings.useProfilerInAdmin')</span>
|
||||||
|
<label>
|
||||||
|
<input class="radio" type="radio" name="useProfilerInAdmin"
|
||||||
|
value="1"
|
||||||
|
@if($profileAdmin) checked @endif />
|
||||||
|
<span>@lang('common.yes')</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input class="radio" type="radio" name="useProfilerInAdmin"
|
||||||
|
value="0"
|
||||||
|
@if(!$profileAdmin) checked @endif />
|
||||||
|
<span>@lang('common.no')</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
@include('admin.settings.snippets.commonSettings', ['field' => 'useProfilerInAdmin'])
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -27,4 +27,6 @@ return [
|
|||||||
"positionFixed" => "fixní",
|
"positionFixed" => "fixní",
|
||||||
"positionStatic" => "statické",
|
"positionStatic" => "statické",
|
||||||
"sidebar" => "Sidebar",
|
"sidebar" => "Sidebar",
|
||||||
|
'no' => 'Ne',
|
||||||
|
'yes' => 'Ano'
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ namespace Templates\PragueTennisCamp\Providers;
|
|||||||
use App\CMS\Helpers\Template;
|
use App\CMS\Helpers\Template;
|
||||||
use Modules\ContactForm\Widgets\Form\Presenter;
|
use Modules\ContactForm\Widgets\Form\Presenter;
|
||||||
|
|
||||||
class ServiceProvider extends \Illuminate\Support\ServiceProvider {
|
class ServiceProvider extends \Illuminate\Support\ServiceProvider
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Register the service provider.
|
* Register the service provider.
|
||||||
*
|
*
|
||||||
@@ -12,12 +13,13 @@ class ServiceProvider extends \Illuminate\Support\ServiceProvider {
|
|||||||
*/
|
*/
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function boot() {
|
public function boot()
|
||||||
if (\App::runningInConsole())
|
{
|
||||||
|
if (\App::runningInConsole()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Presenter::$template = Template::name('widgets.contact.form');
|
Presenter::$template = Template::name('widgets.contact.form');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user