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
|
||||
$setting->value = $value;
|
||||
empty($value) ? $setting->delete() : $setting->save();
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
return redirect()
|
||||
|
||||
@@ -5,8 +5,8 @@ return [
|
||||
'translatedName' => 'profiler::module.name',
|
||||
'translatedDescription' => 'profiler::module.description',
|
||||
'alias' => 'profiler',
|
||||
'handler' => \Modules\Blog\Article\Handlers\Article::class,
|
||||
'providers' => [\Modules\Blog\Article\Providers\ArticleServiceProvider::class],
|
||||
'handler' => \Modules\Profiler\Handlers\ProfileHandler::class,
|
||||
'providers' => [\Modules\Profiler\Providers\ProfilerServiceProvider::class],
|
||||
'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 = [
|
||||
'method',
|
||||
'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 = [
|
||||
'query',
|
||||
'bindings',
|
||||
'time'
|
||||
'time',
|
||||
'http_log_id'
|
||||
];
|
||||
protected $casts = [
|
||||
'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;
|
||||
|
||||
use Pingpong\Modules\Routing\Controller;
|
||||
use App\Http\Controllers\Admin\Controller;
|
||||
use Modules\Profiler\Entities\HttpLog;
|
||||
|
||||
class ProfilerController extends Controller {
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('profiler::index');
|
||||
}
|
||||
|
||||
class ProfilerController extends Controller
|
||||
{
|
||||
public function 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
|
||||
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');
|
||||
Route::get('/', 'ProfilerController@index')->name('profiler.index');
|
||||
Route::get('{httpLog}/queries', 'QueryController@index')->name('queries.index');
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,8 @@ use Modules\Profiler\Entities\QueryLog;
|
||||
|
||||
class Profiler
|
||||
{
|
||||
private $queries = [];
|
||||
|
||||
public function handle(Request $request, $next)
|
||||
{
|
||||
\DB::enableQueryLog();
|
||||
@@ -15,28 +17,47 @@ class Profiler
|
||||
|
||||
public function terminate(Request $request, $response)
|
||||
{
|
||||
$this->logRequest($request);
|
||||
$this->logQueries();
|
||||
$this->queries = \DB::getQueryLog();
|
||||
|
||||
$requestId = $this->logRequest($request);
|
||||
$this->logQueries($requestId);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function logRequest(Request $request)
|
||||
{
|
||||
$url = $request->fullUrl();
|
||||
$method = $request->getMethod();
|
||||
$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 ($queries as $query) {
|
||||
foreach ($this->queries as $query) {
|
||||
QueryLog::create([
|
||||
'query' => $query['query'],
|
||||
'bindings' => $query['bindings'],
|
||||
'time' => $query['time']
|
||||
'query' => $query['query'],
|
||||
'bindings' => $query['bindings'],
|
||||
'time' => $query['time'],
|
||||
'http_log_id' => $httpLogId
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ class ProfilerServiceProvider extends ModuleServiceProvider
|
||||
$this->alias = 'profiler';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Boot the application events.
|
||||
*
|
||||
@@ -28,10 +27,20 @@ class ProfilerServiceProvider extends ModuleServiceProvider
|
||||
{
|
||||
parent::register();
|
||||
|
||||
$this->app['router']->prependMiddlewareToGroup('web', Profiler::class);
|
||||
// $this->app['router']->prependMiddlewareToGroup('admin', Profiler::class);
|
||||
}
|
||||
// register settings form
|
||||
$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()
|
||||
{
|
||||
|
||||
@@ -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')
|
||||
|
||||
<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
|
||||
@@ -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í",
|
||||
"positionStatic" => "statické",
|
||||
"sidebar" => "Sidebar",
|
||||
'no' => 'Ne',
|
||||
'yes' => 'Ano'
|
||||
];
|
||||
|
||||
@@ -4,7 +4,8 @@ namespace Templates\PragueTennisCamp\Providers;
|
||||
use App\CMS\Helpers\Template;
|
||||
use Modules\ContactForm\Widgets\Form\Presenter;
|
||||
|
||||
class ServiceProvider extends \Illuminate\Support\ServiceProvider {
|
||||
class ServiceProvider extends \Illuminate\Support\ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
@@ -12,12 +13,13 @@ class ServiceProvider extends \Illuminate\Support\ServiceProvider {
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function boot() {
|
||||
if (\App::runningInConsole())
|
||||
public function boot()
|
||||
{
|
||||
if (\App::runningInConsole()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Presenter::$template = Template::name('widgets.contact.form');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user