FEATURE: add simple view for requests and queries

This commit is contained in:
Michal Kváček
2017-03-02 20:04:35 +01:00
parent d99c046103
commit 9c90e844b0
23 changed files with 347 additions and 54 deletions
+1 -1
View File
@@ -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()
+3 -3
View File
@@ -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,
]; ];
@@ -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');
});
}
}
@@ -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 -1
View File
@@ -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);
}
} }
+7 -1
View File
@@ -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'));
}
}
+11 -3
View File
@@ -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'); });
}); });
+31 -10
View File
@@ -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>
+2
View File
@@ -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');
} }