PHP Profiler & Developer Toolbar (built for Phalcon)

Overview

Prophiler - A PHP Profiler & Developer Toolbar built for Phalcon

Scrutinizer Code Quality Code Coverage Build Status License Latest Stable Version

Demo

The demo website has been moved to a separate repository: https://github.com/fabfuel/prophiler-demo

Here you can see the toolbar in action: http://prophiler.fabfuel.de/demo.php

Timeline Preview

Installation

You can use composer to install the Prophiler. Just add it as dependency:

"require": {
   	"fabfuel/prophiler": "~1.0",
}

Setup (general)

Setting up the Prophiler and the developer toolbar can be done via the following simple steps. It could all be done in your front-controller (e.g. public/index.php in Phalcon)

1. Initialize the Profiler (as soon as possible)

Generally it makes sense to initialize the profiler as soon as possible, to measure as much execution time as you can. You should initialize the profiler in your front-controller or the bootstrap file right after requiring the Composer autoloader.

$profiler = new \Fabfuel\Prophiler\Profiler();

2. Initialize and register the Toolbar

To visualize the profiling results, you have to initialize and render the Prophiler Toolbar. This component takes care for rendering all results of the profiler benchmarks and other data collectors. Put that at the end of the front-controller.

You can also add other data collectors to the Toolbar, to show e.g. request data like in this example.

$toolbar = new \Fabfuel\Prophiler\Toolbar($profiler);
$toolbar->addDataCollector(new \Fabfuel\Prophiler\DataCollector\Request());
echo $toolbar->render();

You can also easily create you own data collectors, by implementing the DataCollectorInterface and adding an instance to the Toolbar.

...
$toolbar->addDataCollector(new \My\Custom\DataCollector());
...

Additional setup for Phalcon applications

1. Add the profiler to the dependency injection container

Add the profiler instance to the DI container, that other plugins and adapters can use it across the application. This should be done in or after your general DI setup.

$di->setShared('profiler', $profiler);

2. Initialize the plugin manager

The plugin manager registers all included Phalcon plugins automatically and attaches them to the events manager. To make the plugins work properly, make sure that the default events manager is attached to your Dispatcher, View and Connection services.

$pluginManager = new \Fabfuel\Prophiler\Plugin\Manager\Phalcon($profiler);
$pluginManager->register();

Custom Benchmarks

You can easily add custom benchmarks to your code:

$benchmark = $profiler->start('\My\Class::doSomething', ['additional' => 'information'], 'My Component');
...
$profiler->stop($benchmark);

Or stop without passing the benchmark

In some scenarios (e.g. custom adapters) it might be hard to pass the received benchmark to the stop() method. Alternatively you can simply omit the $benchmark parameter. If that is the case, the profiler simply stops the last started benchmark, but it is not possible to run overlapping benchmarks.

$profiler->start('\My\Class::doSomeOtherThing', ['additional' => 'information'], 'My Component');
...
$profiler->stop();

Aggregations

Prophiler now features benchmark aggregations. These give you a lot more insights and are extremely useful to:

  • quickly see the total number of recurring executions (e.g. database or cache queries)
  • analyze minimum, maximum and average execution times of recurring executions
  • easily see (e.g. accidentally) recurring executions of the same database query
  • get a warning, if the total number of executions exceeds a custom threshold
  • get a warning, if the maximum execution time exceeds a custom threshold

Setup

Prophiler comes with some aggregators, but you can easily create your own. To Set up an aggregator, all you need to do is to register the aggregator at the profiler instance:

$profiler->addAggregator(new \Fabfuel\Prophiler\Aggregator\Database\QueryAggregator());
$profiler->addAggregator(new \Fabfuel\Prophiler\Aggregator\Cache\CacheAggregator());

That's it. You immediately see all database and cache queries, grouped by command/query, including the total number of executions, the total duration of all executions as well as the minimum, maximum and average execution time.

Logging

You can use Prophiler to log events and other data and view it in the timeline and in the separate "Logs" tab. If you already have a logging infrastructure, you can add the PSR-3 compliant Logger adapter to it. Otherwise you can also just instantiate and use it directly:

$logger = new \Fabfuel\Prophiler\Adapter\Psr\Log\Logger($profiler);
$logger->warning('This is a warning!', ['some' => 'context']);
$logger->debug('Some debugging information', ['query' => ['user' => 12345], 'foo' => 'bar']);

Adapters and Decorators

Doctrine

To profile all SQL queries made by Doctrine, you just have to register the SQLLogger adapter in your Doctrine configuration, for example in your bootstrap.php like that:

$sqlLogger = new Fabfuel\Prophiler\Adapter\Doctrine\SQLLogger($profiler);
$entityManager->getConnection()->getConfiguration()->setSQLLogger($sqlLogger);

PDO

To profile your PDO database actions, you can use the Prophiler PDO decorator. It will record all query() & exec() calls and prepared statements as well. Just decorate your PDO instance with the Prophiler decorator and use that instead:

$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'password');
$db = new \Fabfuel\Prophiler\Decorator\PDO\PDO($pdo, $profiler);

$db->query('SELECT * from users');
$db->exec('DELETE FROM users WHERE active = 0');
$db->prepare('SELECT * from users WHERE userId = ?');

Cache

To profile Phalcon cache backend requests, you only need to decorate the cache backend with the BackendDecorator. It will benchmark all cache operations automatically. Here is an example with the APC backend:

$cacheFrontend = new \Phalcon\Cache\Frontend\Data(['lifetime' => 172800]);
$cacheBackend = new \Phalcon\Cache\Backend\Apc($cacheFrontend, ['prefix' => 'app-data']);

$cache = \Fabfuel\Prophiler\Decorator\Phalcon\Cache\BackendDecorator($cacheBackend, $profiler);

Elasticsearch

To profile Elasticsearch requests, you only need to decorate the Elasticsearch client with the ClientDecorator:

$elasticsearch = new Elasticsearch\Client(['your' => 'config']);
$client = new \Fabfuel\Prophiler\Decorator\Elasticsearch\ClientDecorator($client, $profiler);

Tips

Record session writing

To record session writing, you can commit (this is also known as session_write_close()) the session before rendering the toolbar

session_commit();
Comments
  • fix trailing </td>, explicitly check for string type, dump object type

    fix trailing , explicitly check for string type, dump object type

    This PR does 3 things:

    1. with these changes numerical values (int, float, etc..) would now be using the fallback output style using var_dump instead of the nl2br() output that applied before. This is a slight change in behaviour which you might not want in a "hotfix" - let me know and I will restore the previous behaviour for numericals
    2. fixed: objects that didn't resolve to true for is_array in the data.phtml view no longer throw warnings for attempting to echo them using nl2br. This is achieved by defaulting to a var_dump instead, which results in a behaviour change described in 1)
    3. fixed: without xdebug loaded, the output of arrays in array.phtml allowed html to be rendered unescaped, which broke the toolbar (think writing cms content into the cache). This was solved by starting a buffer and applying htmlentities. The behaviour for the new var_dump fallback also requires this.

    I can has hotfix tag please? :D

    opened by mdular 9
  • PHP 7 not supported?

    PHP 7 not supported?

    $ composer require fabfuel/prophiler
    Using version ^1.5 for fabfuel/prophiler
    ./composer.json has been updated
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of packages.
    
      Problem 1
        - Installation request for fabfuel/prophiler ^1.5 -> satisfiable by fabfuel/prophiler[1.5.0].
        - fabfuel/prophiler 1.5.0 requires php ~5.4 -> your PHP version (7.0.0RC7) or "config.platform.php" value does not satisfy that requirement.
    
    opened by geerteltink 7
  • Fix probably need for css

    Fix probably need for css

    Hi,

    When queries are logged it is not possible to see the full queries. It would be nice if there is a way to see the queries that are big. See screenshot .

    screenshot from 2016-01-15 23-06-03

    See the 3rd one looks truncated due to styling issue.

    opened by harikt 6
  • how to trace timeline on phalcon?

    how to trace timeline on phalcon?

    Hi, i cant view nothing on timeline :( i put in my index.php:

    include APP_PATH . 'vendor/autoload.php';
    

    $profiler = new \Fabfuel\Prophiler\Profiler();

    and the end of file: after: echo $application->handle()->getContent();

    i put:

    $toolbar = new \Fabfuel\Prophiler\Toolbar($profiler);
    $toolbar->addDataCollector(new \Fabfuel\Prophiler\DataCollector\Request());
    echo $toolbar->render();
    

    too:

    $di = new FactoryDefault();
    $di->setShared('profiler', $profiler);
    

    i dont know where put:

     $pluginManager = new \Fabfuel\Prophiler\Plugin\Manager\Phalcon($profiler);
     $pluginManager->register();
    

    at the end of my index.php too?

    Help!, what I'm missing?

    opened by hardlick 6
  • [FIX] Loading jQuery fixed in case the main document didn't use it

    [FIX] Loading jQuery fixed in case the main document didn't use it

    Hi!

    While working on project draft with I experienced problems loading jQuery using the code provided currently by Prophiler. All functionalities based on jQuery didn't work in result. The fix was tested on OSX 10.11 with:

    • Google Chrome 46.0.2490.86 (64-bit)
    • Firefox 42.0
    • Safari Version 9.0 (11601.1.56)
    opened by wkukielczak 5
  • Fantastic but I have issues

    Fantastic but I have issues

    I'm building an application that is built on mruz base-app version 1.3 (https://github.com/mruz/base-app/releases) with Phalcon 1.3.4.

    I have tried Prophiler on a simple Phalcon app, and it seems to work fine, although I couldn't get anything displaying on time line.

    The problem is on my app (based on mruz base-app) is that Prophiler results in really slow page loads. I have my app running on a vagrant box, and during page load, with Prophiler added, the CPU will some times max out. While the page displays ok, if I view the page source, it seems it is repeating or looping. The page source and HTML for prophiler is repeated over and over. Very strange, and unfortunately it makes Prophiler unusable for me on this project.

    Any idea what the problem might be and how I can fix it?

    opened by al35mm 4
  • Add afterRender event in toolbar

    Add afterRender event in toolbar

    So that you don't have to call

    echo $toolbar->render();
    

    now the call can be

    
    $di->set('profiler',
        function () {
            return new \Fabfuel\Prophiler\Profiler();
        },
        true
    );
    
    $di->set('toolbar',
        function () use ($di) {
            $profiler = $di->get('profiler');
            $toolbar = new \Fabfuel\Prophiler\Toolbar($profiler);
            $toolbar->setEventsManager($di->get('eventsManager'));
            return $toolbar;
        },
        true
    );
    
    $toolbar = $di->get('toolbar');
    
    opened by ogarbe 4
  • Is it possible to see an array detail in log

    Is it possible to see an array detail in log

    Hello,

    I would like to debug the content of an array. I tried

    $logger->debug($my_array);
    

    But all I can see is "array". If I add print_r, nothing is readable anymore. Is there a way ?

    Cheers

    opened by Merrick28 3
  • null DB Service problem

    null DB Service problem

    if possible you can check whether $this->db is set or not https://github.com/fabfuel/prophiler/blob/develop/src/Fabfuel/Prophiler/Plugin/Manager/Phalcon.php#L46

    opened by TheCodemasterZz 3
  • PDO Profiling

    PDO Profiling

    Hi,

    First of all great tool you wrote and thanks. I've recently updated prophiler on my existing codebase from 1.1 to 2.0 and tried to apply PDO profiling. Since i heavily use prepared statements in my project i noticed the PDO profiling breaking pretty fast since it was relying on PHP::PDO and not on Phalcon\Db\Adapter\Pdo (ie: tableExists is implicitly called).

    Is there a reason PHP::PDO is required instead of Phalcon's extension?

    I've modified the code locally (which i can fork and PR) to work with prepared statements.

    Here's an excerpt from my code which causes the following exception:

    PHP Warning: call_user_func_array() expects parameter 1 to be a valid callback, class 'PDO' does not have a method 'tableexists' in ~\libraries\fabfuel\prophiler\src\Fabfuel\Prophiler\Decorator\PDO\PDO.php on line 45

    # services.php
    ...
    $di['db'] = function () use ($di) {
        $mode = require __DIR__.'/mode.php';
        $dbFilePath = __DIR__."/database-{$mode}.php";
    
        if (is_file($dbFilePath)) {
            $dbconfig = require_once $dbFilePath;
            // Slightly altered to get PDO statement with existing config
            $db = new DbAdapter($dbconfig->database->toArray());
            $dbhandler = $db->getInternalHandler();
    
            return new \Fabfuel\Prophiler\Decorator\PDO\PDO(
                // new DbAdapter($dbconfig->database->toArray()),
                $dbhandler, // object(PDO)
                $di->get('profiler')
            );
        } else {
            throw new Exception("Unable to find database configuration.");
        }
    };
    ...
    
    # router.php
    ...
                // Split URI into parts for quering the database
                preg_match('~/*([\w\d-_]+)~iu', $router->getRewriteUri(), $matches);
    
                if (!empty($matches[1])) {
                    @list($uri, $uriIndex) = explode('-', $matches[1]);
    
                    // Lookup route in the databse
                    $route = self::findFirst([
                        'conditions' => 'uri = ?1 AND uri_index = ?2',
                        'bind' => [1 => $uri, 2 => (int) (!empty($uriIndex)) ? $uriIndex : 0],
                    ]);
    
                    if ($route) {
                        // Match! Add route to router
                        $router->add(
                            $router->getRewriteUri(),
                            [
                                'module' => $route->module,
                                'controller' => $route->controller,
                                'action' => $route->action,
                                'params' => unserialize($route->params)
                            ]
                        );
                    }
                }
    ...
    
    wontfix 
    opened by PBXg33k 3
  • PSR Logger Interface cannot be found

    PSR Logger Interface cannot be found

    I just came across with this issue, any idea?

    Fatal error: Interface 'Psr\Log\LoggerInterface' not found in /var/www/clients/client2/web4/web/app/services/Fabfuel/Prophiler/Adapter/Psr/Log/Logger.php on line 12

    opened by andrewtheone 2
  • Update db plugin to require generic abstract db adapter

    Update db plugin to require generic abstract db adapter

    Phalcon 4 compatibility

    Fixes the following error:

    TypeError: Argument 2 passed to Fabfuel\Prophiler\Plugin\Phalcon\Db\AdapterPlugin::beforeQuery() must be an instance of Phalcon\Db\Adapter, instance of Phalcon\Db\Adapter\Pdo\Mysql given

    Once fixed the toolbar seems to be functioning fine when initialised as follows:

    $profiler = new \Fabfuel\Prophiler\Profiler();
    $di->setShared('profiler', $profiler);
    
    $profiler->addAggregator(new \Fabfuel\Prophiler\Aggregator\Database\QueryAggregator());
    $profiler->addAggregator(new \Fabfuel\Prophiler\Aggregator\Cache\CacheAggregator());
    
    $pluginManager = new \Fabfuel\Prophiler\Plugin\Manager\Phalcon($profiler);
    $pluginManager->register();
    

    image

    Queries are being logged, request info is available and timeline/memory/etc are being displayed. Not a full compatibility test but seems to be mostly working.

    opened by Caffe1neAdd1ct 5
  • Need little help in implementing

    Need little help in implementing

    Hi, I am in learning phase and wanted to test it out on sample App https://github.com/phalcon/vokuro . Can you advice where and what to add so that can see queries, cache and user details too, right now only showing REQUEST and General which you have added by default.

    It will really help to get better understanding of phalcon in general.

    Thanks

    opened by iRickyJ 0
  • Small error in README.md

    Small error in README.md

    There is:

    $cache = \Fabfuel\Prophiler\Decorator\Phalcon\Cache\BackendDecorator($cacheBackend, $profiler);
    

    There should be:

    $cache = new \Fabfuel\Prophiler\Decorator\Phalcon\Cache\BackendDecorator($cacheBackend, $profiler);
    
    opened by evolic 1
Releases(1.6.0)
  • 1.6.0(Sep 16, 2017)

    New Features

    • PHP 7.0 and 7.1 support

    Changes

    • BREAKING: Removed PHP 5.4 support
    • Removed composer.lock
    • Removed demo page from the library repository (moved to https://github.com/fabfuel/prophiler-demo)

    Fixes

    • Fixed trailing
    • Convert special characters to HTML entities
    Source code(tar.gz)
    Source code(zip)
  • 1.4.0(Aug 8, 2015)

    New Features

    • Aggregations
    • Phalcon Cache Backend Decorator
    • ElasticSearch Client Decorator
    • Automatic EventsManger registration

    Changes

    • internally handling all durations in milliseconds (instead of seconds)
    • Docker config improvements

    Aggregations

    Prophiler now features benchmark aggregations. These give you a lot more insights and are extremely useful to:

    • quickly see the total number of recurring executions (e.g. database or cache queries)
    • analyze minimum, maximum and average execution times of recurring executions
    • easily see (e.g. accidentally) recurring executions of the same database query
    • get a warning, if the total number of executions exceeds a custom threshold
    • get a warning, if the maximum execution time exceeds a custom threshold

    Setup

    Prophiler comes with some aggregators, but you can easily create your own. To Set up an aggregator, all you need to do is to register the aggregator at the profiler instance:

    $profiler->addAggregator(new \Fabfuel\Prophiler\Aggregator\Database\QueryAggregator());
    $profiler->addAggregator(new \Fabfuel\Prophiler\Aggregator\Cache\CacheAggregator());
    

    That's it. You immediately see all database and cache queries, grouped by command/query, including the total number of executions, the total duration of all executions as well as the minimum, maximum and average execution time.

    Phalcon Cache Backend Decorator

    To profile Phalcon cache backend requests, you only need to decorate the cache backend with the BackendDecorator. It will benchmark all cache operations automatically. Here is an example with the APC backend:

    $cacheFrontend = new \Phalcon\Cache\Frontend\Data(['lifetime' => 172800]);
    $cacheBackend = new \Phalcon\Cache\Backend\Apc($cacheFrontend, ['prefix' => 'app-data']);
    
    $cache = \Fabfuel\Prophiler\Decorator\Phalcon\Cache\BackendDecorator($cacheBackend, $profiler);
    

    ElasticSearch Client Decorator

    To profile Elasticsearch requests, you only need to decorate the Elasticsearch client with the ClientDecorator:

    $elasticsearch = new Elasticsearch\Client(['your' => 'config']);
    $client = new \Fabfuel\Prophiler\Decorator\Elasticsearch\ClientDecorator($client, $profiler);
    

    Automatic EventsManger registration

    Prophiler now uses existing EventsManagers when attaching the Db, Dispatcher and View plugins and uses the default one as fallback, if no EventsManager is defined.

    Source code(tar.gz)
    Source code(zip)
Owner
Fabian Fuelling
Engineer. Entrepreneur. Musician. Berliner.
Fabian Fuelling
Developer Toolbar for Magento2

Developer Toolbar for Magento2 About Hope this debug toolbar can speed up Magento2 development module. Any feedback and idea to improve this toolbar w

Vincent Pietri 423 Dec 28, 2022
It allows frontend developer to send ajax requests and return a custom information from the server without a php developer help

[Magento 1 Extension] It allows frontend developer to send ajax requests and return a custom information from the server without a php developer help (without any php code).

Vladimir Fishchenko 62 Apr 1, 2022
A Phalcon paginator adapter for Phalcon Collections

Phalcon Collection Paginator A Phalcon paginator adapter for Phalcon Collections Why create this? Being familiar with the various Pagination data adap

Angel S. Moreno 2 Oct 7, 2022
Magento Chrome Toolbar for MSP_DevTools

Magento Chrome Toolbar for MSP DevTools Magento Chrome Toolbar is a chrome extension to be used with MSP_DevTools for Magento 1 or Magento 2. This ext

MageSpecialist 308 Dec 10, 2022
A sampling profiler for PHP written in PHP, which reads information about running PHP VM from outside of the process.

Reli Reli is a sampling profiler (or a VM state inspector) written in PHP. It can read information about running PHP script from outside of the proces

null 272 Dec 22, 2022
A sampling profiler for PHP written in PHP, which reads information about running PHP VM from outside of the process.

Reli Reli is a sampling profiler (or a VM state inspector) written in PHP. It can read information about running PHP script from outside of the proces

null 258 Sep 15, 2022
Magento 2 Profiler

Magento 2 - Debug module Module for debugging Magento 2 performance. It works without overwriting any core files and it can be installed with composer

ClawRock 44 Oct 13, 2022
Learn to apply best practices as a PHP backend developer

PHP eCommerce Project Here are the things that this repo will cover: Object oriented programming principles and best practices Object oriented session

Muhammad Salah 0 Aug 2, 2022
Collection of PHP functions, mini classes and snippets for everyday developer's routine life

JBZoo / Utils Collection of PHP functions, mini classes and snippets for everyday developer's routine life. Install composer require jbzoo/utils Usage

JBZoo Toolbox 776 Jun 2, 2022
dEveloper Module for PHP-Nuke Titanium v4.0.0

Titanium_SandBox Titanium_SandBox The Titanium Sandbox Module v4.0.0b: This module is only for PHP-Nuke Titanium application builders. A sandbox is a

Ernest Allen Buffington (The Ghost) 3 Oct 3, 2022
Interview project for Fullstack Developer.

Interview Project Fullstack Requires PHP: 7.0 WP requires at least: 5.7 WP tested up to: 5.7 WC requires at least: 5.6.0 WC tested up to: 5.8.0 Stable

Universal Yums 1 Oct 27, 2021
⚗️ Adds code analysis to Laravel improving developer productivity and code quality.

⚗️ About Larastan Larastan was created by Can Vural and Nuno Maduro, got artwork designed by @Caneco, is maintained by Can Vural, Nuno Maduro, and Vik

Nuno Maduro 4.4k Jan 4, 2023
Resources for the Magento 2 Certified Professional Front End Developer exam

Magento 2 Certified Professional Front End Developer Training Resources Below are the 6 slide decks used internally at Fisheye to help us prepare for

Fisheye Academy 109 Oct 21, 2022
📚Magento 2 Certified Professional Developer Plus Exam

?? Magento2 Certified Professional Developer Plus There are notes for those who preparing to pass Magento 2 Certified Professional Developer Plus exam

Roman Glushko 80 Aug 20, 2022
Preparation notes for Magento 2 Certified Professional Cloud Developer exam

Overview Magento 2 Certified Professional Cloud Developer 1. Topics 13% 1 - Commerce Cloud Fundamentals (8 questions) 9% 2 - Local Environment (6 ques

Magento Notes 78 Dec 26, 2022
Preparation notes for Magento 2 Certified Professional Developer exam

Overview Magento 2 Certified Professional Developer notes 1. Topics 18% 1 - Magento Architecture and Customization Techniques (11 questions) modules,

Magento Notes 669 Dec 19, 2022
Warden is a CLI utility for orchestrating Docker based developer environments

Warden Warden is a CLI utility for orchestrating Docker based developer environments, and enables multiple local environments to run simultaneously wi

David Alger 314 Dec 2, 2022
Developer-friendly framework heavily inspired by Laravel and based on Timber and Wpemerge solutions for WordPress themes development with Bedrock folder structure

Lightweight Brocooly (Brocket) Improved Controllers, Middleware and Routers, but slightly less powerful Container Open beta. Package in development Cr

Ihar Aliakseyenka 3 Mar 4, 2022
Membuat Project Untuk Tes Web Developer - Digitaliz

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Indra Wijaya 1 Jan 24, 2022