ClockWork
Clockwork is a browser extension, providing tools for debugging and profiling your PHP applications
Install
Install the Clockwork library via Composer
$ composer require itsgoingd/clockwork
Publish config
vendor:publish
Clockwork comes with a clock() helper function, which provides an easy way to add records to the Clockwork log and events to the timeline.
Usage
To interact with the data collected by Clockwork, you will need to
-
install the Chrome extension
-
or the Firefox add-on
-
or use the web UI
http://your.app/__clockwork
Config ( clockwork.php)
'enable' => env('CLOCKWORK_ENABLE', null),
'features' => [
'database' => [
'collect_queries' => env('CLOCKWORK_DATABASE_COLLECT_QUERIES', true),
],
'routes' => [
'enabled' => env('CLOCKWORK_ROUTES_ENABLED', true)
],
'views' => [
'enabled' => env('CLOCKWORK_VIEWS_ENABLED', true)
]
],
'web' => env('CLOCKWORK_WEB', true),
'storage' => env('CLOCKWORK_STORAGE', 'sql'),
'storage_files_path' => env('CLOCKWORK_STORAGE_FILES_PATH', storage_path('clockwork')),
'storage_expiration' => env('CLOCKWORK_STORAGE_EXPIRATION', 60 * 2),
'authentication' => env('CLOCKWORK_AUTHENTICATION', false),
'authentication_password' => env('CLOCKWORK_AUTHENTICATION_PASSWORD', 'VerySecretPassword'),
'filter_uris' => [
'/horizon/.*', // Laravel Horizon requests
],
'register_helpers' => env('CLOCKWORK_REGISTER_HELPERS', true),
Config (clockwork.php)
<?php
return [
/*
|--------------------------------------------------------------------------
| Enable Clockwork
|--------------------------------------------------------------------------
|
| You can explicitly enable or disable Clockwork here. When enabled, special
| headers for communication with the Clockwork Chrome extension will be
| included in your application responses and requests data will be available
| at /__clockwork url.
| When set to null, Clockwork behavior is controlled by app.debug setting.
| Default: null
|
*/
'enable' => env('CLOCKWORK_ENABLE', null),
/*
|--------------------------------------------------------------------------
| Features
|--------------------------------------------------------------------------
|
| You can enable or disable various Clockwork features here. Some features
| accept additional configuration (eg. slow query threshold for database).
|
*/
'features' => [
// Cache usage stats and cache queries including results
'cache' => [
'enabled' => env('CLOCKWORK_CACHE_ENABLED', true),
// Collect cache queries including results (high performance impact with a high number of queries)
'collect_queries' => env('CLOCKWORK_CACHE_QUERIES', false)
],
// Database usage stats and queries
'database' => [
'enabled' => env('CLOCKWORK_DATABASE_ENABLED', true),
// Collect database queries (high performance impact with a very high number of queries)
'collect_queries' => env('CLOCKWORK_DATABASE_COLLECT_QUERIES', false),
// Query execution time threshold in miliseconds after which the query will be marked as slow
'slow_threshold' => env('CLOCKWORK_DATABASE_SLOW_THRESHOLD'),
// Collect only slow database queries
'slow_only' => env('CLOCKWORK_DATABASE_SLOW_ONLY', false),
// Detect and report duplicate (N+1) queries
'detect_duplicate_queries' => env('CLOCKWORK_DATABASE_DETECT_DUPLICATE_QUERIES', false)
],
// Sent emails
'emails' => [
'enabled' => env('CLOCKWORK_EMAILS_ENABLED', true),
],
// Dispatched events
'events' => [
'enabled' => env('CLOCKWORK_EVENTS_ENABLED', true),
// Ignored events (framework events are ignored by default)
'ignored_events' => [
// App\Events\UserRegistered::class,
// 'user.registered'
],
],
// Laravel log (you can still log directly to Clockwork with laravel log disabled)
'log' => [
'enabled' => env('CLOCKWORK_LOG_ENABLED', true)
],
// Dispatched queue jobs
'queue' => [
'enabled' => env('CLOCKWORK_QUEUE_ENABLED', true)
],
// Redis commands
'redis' => [
'enabled' => env('CLOCKWORK_REDIS_ENABLED', true)
],
// Routes list
'routes' => [
'enabled' => env('CLOCKWORK_ROUTES_ENABLED', true)
],
// Rendered views including passed data (high performance impact with large amount of data passed to views)
'views' => [
'enabled' => env('CLOCKWORK_VIEWS_ENABLED', false)
]
],
/*
|--------------------------------------------------------------------------
| Enable web UI
|--------------------------------------------------------------------------
|
| Enable or disable the Clockwork web UI available at http://your.app/__clockwork.
| You can also set whether to use the dark theme by default.
| Default: true
|
*/
'web' => env('CLOCKWORK_WEB', true),
'web_dark_theme' => env('CLOCKWORK_WEB_DARK_THEME', true),
/*
|--------------------------------------------------------------------------
| Enable data collection, when Clockwork is disabled
|--------------------------------------------------------------------------
|
| This setting controls, whether data about application requests will be
| recorded even when Clockwork is disabled (useful for later analysis).
| Default: false
|
*/
'collect_data_always' => env('CLOCKWORK_COLLECT_DATA_ALWAYS', false),
/*
|--------------------------------------------------------------------------
| Metadata storage
|--------------------------------------------------------------------------
|
| You can configure how are the metadata collected by Clockwork stored.
| Valid options are: files or sql.
| Files storage stores the metadata in one-per-request files in a specified
| directory.
| Sql storage stores the metadata as rows in a sql database. You can specify
| the database by name if defined in database.php or by path to Sqlite
| database. Database table will be automatically created.
| Sql storage requires PDO.
|
*/
'storage' => env('CLOCKWORK_STORAGE', 'sql'),
'storage_files_path' => env('CLOCKWORK_STORAGE_FILES_PATH', storage_path('clockwork')),
// Compress the metadata files using gzip, trading a little bit of performance for lower disk usage
'storage_files_compress' => env('CLOCKWORK_STORAGE_FILES_COMPRESS', false),
'storage_sql_database' => env('CLOCKWORK_STORAGE_SQL_DATABASE', storage_path('clockwork.sqlite')),
'storage_sql_table' => env('CLOCKWORK_STORAGE_SQL_TABLE', 'clockwork'),
/*
|--------------------------------------------------------------------------
| Metadata expiration
|--------------------------------------------------------------------------
|
| Maximum lifetime of the metadata in minutes, metadata for older requests
| will automatically be deleted when storing new requests.
| When set to false, metadata will never be deleted.
| Default: 1 week
|
*/
'storage_expiration' => env('CLOCKWORK_STORAGE_EXPIRATION', 60 * 2),
/*
|--------------------------------------------------------------------------
| Authentication
|--------------------------------------------------------------------------
|
| Clockwork can be configured to require authentication before allowing
/ access to the collected data. This is recommended when the application
/ is publicly accessible, as the metadata might contain sensitive information.
/ Setting to "true" enables authentication with a single password set below,
/ "false" disables authentication.
/ You can also pass a class name of a custom authentication implementation.
/ Default: false
|
*/
'authentication' => env('CLOCKWORK_AUTHENTICATION', false),
'authentication_password' => env('CLOCKWORK_AUTHENTICATION_PASSWORD', 'VerySecretPassword'),
/*
|--------------------------------------------------------------------------
| Disable data collection for certain URIs
|--------------------------------------------------------------------------
|
| You can disable data collection for specific URIs by adding matching
| regular expressions here.
|
*/
'filter_uris' => [
'/horizon/.*', // Laravel Horizon requests
'/telescope/.*', // Laravel Telescope requests
'/admin/voyager-assets*'
],
/*
|--------------------------------------------------------------------------
| Enable collecting of stack traces
|--------------------------------------------------------------------------
|
| This setting controls, whether log messages and certain data sources, like
/ the database or cache data sources, should collect stack traces.
/ You might want to disable this if you are collecting 100s of queries or
/ log messages, as the stack traces can considerably increase the metadata size.
/ You can force collecting of stack trace for a single log call by passing
/ [ 'trace' => true ] as $context.
| Default: true
|
*/
'stack_traces' => [
// Enable or disable collecting of stack traces, when disabled only caller file and line number is collected
'enabled' => env('CLOCKWORK_STACK_TRACES_ENABLED', true),
// List of vendor names to skip when determining caller, common vendor are automatically added
'skip_vendors' => [
// 'phpunit'
],
// List of namespaces to skip when determining caller
'skip_namespaces' => [
// 'Laravel'
],
// List of class names to skip when determining caller
'skip_classes' => [
// App\CustomLog::class
],
// Limit of frames to be collected
'limit' => env('CLOCKWORK_STACK_TRACES_LIMIT', 10)
],
/*
|--------------------------------------------------------------------------
| Serialization
|--------------------------------------------------------------------------
|
| Configure how Clockwork serializes the collected data.
| Depth limits how many levels of multi-level arrays and objects have
| extended serialization (rest uses simple serialization).
| Blackbox allows you to specify classes which contents should be never
| serialized (eg. a service container class).
| Lowering depth limit and adding classes to blackbox lowers the memory
| usage and processing time.
|
*/
'serialization_depth' => env('CLOCKWORK_SERIALIZATION_DEPTH', 10),
'serialization_blackbox' => [
\Illuminate\Container\Container::class,
\Illuminate\Foundation\Application::class,
\Laravel\Lumen\Application::class
],
/*
|--------------------------------------------------------------------------
| Register helpers
|--------------------------------------------------------------------------
|
| This setting controls whether the "clock" helper function will be registered. You can use the "clock" function to
| quickly log something to Clockwork or access the Clockwork instance.
|
*/
'register_helpers' => env('CLOCKWORK_REGISTER_HELPERS', true),
/*
|--------------------------------------------------------------------------
| Send Headers for AJAX request
|--------------------------------------------------------------------------
|
| When trying to collect data the AJAX method can sometimes fail if it is
| missing required headers. For example, an API might require a version
| number using Accept headers to route the HTTP request to the correct
| codebase.
|
*/
'headers' => [
// 'Accept' => 'application/vnd.com.whatever.v1+json',
],
/*
|--------------------------------------------------------------------------
| Server-Timing
|--------------------------------------------------------------------------
|
| Clockwork supports the W3C Server Timing specification, which allows for
/ collecting a simple performance metrics in a cross-browser way. Eg. in
/ Chrome, your app, database and timeline event timings will be shown
/ in the Dev Tools network tab.
/ This setting specifies the max number of timeline events that will be sent.
| When set to false, Server-Timing headers will not be set.
| Default: 10
|
*/
'server_timing' => env('CLOCKWORK_SERVER_TIMING', 10)
];
- request data - headers, GET and POST data, cookies
- performance metrics
- log messages
- database queries
- cache usage
- application events
- session data
- sent emails
- rendered views
Collected data
Collecting data about your application runtime is the core functionality of Clockwork. Include:
Some of the data is not collected by default as it may considerably increase the metadata size:
- cache queries (cache stats are still collected)
- rendered views
- application routes
Request, Performance metric
Database
'collect_queries' => env('CLOCKWORK_DATABASE_COLLECT_QUERIES', true),
'slow_only' => env('CLOCKWORK_DATABASE_SLOW_ONLY', false),
'detect_duplicate_queries' => env('CLOCKWORK_DATABASE_DETECT_DUPLICATE_QUERIES', true)
Database
Events
Routes
Views
Cache
Logging
// All data logged using the Laravel log methods will also appear in the Clockwork
Log::debug('An informational message.');
// Logging data to Clockwork can be done using the helper function, which even supports logging multiple values at once
clock(User::first(), auth()->user(), $username);
// If you want to specify a log level, you can use the long-form call
clock()->info("User {$username} logged in!");
// The clock() helper function *returns it's first argument*, so you can easily add inline debugging statements to your code:
User::create( clock($request->all()) );
// You can use the *trace* option to make Clockwork explicitly collect stack trace for a particular message.
clock()->info("Trace this message!", [ 'trace' => true ])
Logging
clock($posts);
dump($posts);
vs
Timeline
// To add a custom event to the timeline, you'll need to start an event with an unique name and description first
clock()->startEvent('mybox-api-call', "Very slow dumb API");
// After executing the tracked block of code, you can end the event, using it's unique name.
clock()->endEvent('mybox-api-call')
Timeline
Userdata
Show specific data in a new tab:
$cart = clock()->userData('cart') ->title('Cart'); $cart->counters([ 'Products' => 3, 'Value' => '949.80€' ]); $cart->table('Products', [ [ 'Product' => 'iPad Pro 10.5" 256G Silver', 'Price' => '849 €' ], [ 'Product' => 'Smart Cover iPad Pro 10.5 White', 'Price' => '61.90 €' ], [ 'Product' => 'Apple Lightning to USB 3 Camera Adapter', 'Price' => '38.90 €' ] ]);
Userdata
Simple log:
Instead of logging the cart contents and looking for them in the log tab, we can make a new "Cart" tab which will show some stats and the cart contents:
Xdebug profiler
Setup (Linux)
Install the Xdebug extension via PECL (part of your PHP installation):
zend_extension="/usr/local/php/modules/xdebug.so" xdebug.profiler_enable_trigger=1
Enable the PHP extension in your php.ini (location of php.ini and the xdebug extension path will depend on your operating system):
$ pecl install xdebug
Xdebug profiler
Setup (Windows)
Download php_xdebug-2.7.2-7.2-vc15-x86_64.dll
Move the downloaded file to
d:\ospanel\modules\php\PHP-7.2-x64\ext
Update php.ini and change the line
zend_extension = d:\ospanel\modules\php\PHP-7.2-x64\ext\php_xdebug-2.7.2-7.2-vc15-x86_64.dll
Restart the webserver
Xdebug profiler
Setup (Docker)
Dockerfile
FROM php:7.2-fpm
RUN apt-get update && apt-get install -y wget git unzip \
&& pecl install xdebug-2.7.1 \
&& docker-php-ext-enable xdebug
ADD ./php.ini /usr/local/etc/php/php.ini
RUN wget https://getcomposer.org/installer -O - -q \
| php -- --install-dir=/bin --filename=composer --quiet
WORKDIR /var/www
max_execution_time = 1000
max_input_time = 1000
php.ini
Xdebug profiler
Setup (Docker)
docker-compose.yml
version: '3'
services:
php-fpm:
# ...
environment:
XDEBUG_CONFIG: "remote_host=192.168.220.1 remote_enable=1 profiler_enable_trigger=1"
PHP_IDE_CONFIG: "serverName=Docker"
networks:
- internal
nginx:
# ...
networks:
- internal
networks:
internal:
driver: bridge
ipam:
driver: default
config:
- subnet: 192.168.220.0/28
Xdebug profiler
Setup (Docker)
docker-compose.yml
version: '3'
services:
php-fpm:
build:
context: docker/php-fpm
volumes:
- ./:/var/www
environment:
XDEBUG_CONFIG: "remote_host=192.168.220.1 remote_enable=1 profiler_enable_trigger=1"
PHP_IDE_CONFIG: "serverName=Docker"
networks:
- internal
nginx:
build:
context: docker/nginx
volumes:
- ./:/var/www
ports:
- "80:80"
depends_on:
- php-fpm
networks:
- internal
networks:
internal:
driver: bridge
ipam:
driver: default
config:
- subnet: 192.168.220.0/28
It is still not recommended to run Clockwork in production or environments that might contain sensitive customer data!
!!!
Bonus
config / debugbar.php
'clockwork' => true
The Debugbar can emulate the Clockwork headers, so you can use the Chrome Extension, without the server-side code. It uses Debugbar collectors instead.
Clockwork (Laravel)
By TAlex
Clockwork (Laravel)
- 1,765