Installation Install the Clockwork library via Composer. $ composer require itsgoingd/clockwork Congratulations, you are done! To enable more features like commands or queue jobs profiling, publish the configuration file via the vendor:publish Artisan command. Note: If you are using the Laravel route cache, you will need to refresh it using the route:cache Artisan command. Old Laravel For Laravel versions older than 5.5, you'll need to register the service provider, in your config/app.php : 'providers' => [ ... Clockwork\Support\Laravel\ClockworkServiceProvider::class ] If you'd like to use the Facade, add following to your config/app.php : 'aliases' => [ ... 'Clockwork' => Clockwork\Support\Laravel\Facade::class, ]

Lumen Install the Clockwork library via Composer. $ composer require itsgoingd/clockwork Once Clockwork is installed, you need to register the Clockwork service provider, in your bootstrap/app.php : $app->register(Clockwork\Support\Lumen\ClockworkServiceProvider::class); To enable more features like commands or queue jobs profiling use enviroment variables, see full list of available settings. Note: For collecting database queries you'll need to enable $app->withEloquent() in bootstrap/app.php , this has no performance impact if your app executes database queries on most requests.

Vanilla Install the Clockwork library via Composer. $ composer require itsgoingd/clockwork Initialize Clockwork early in your application. $clockwork = Clockwork\Support\Vanilla\Clockwork::init(); If you are using a dependency injection container it might be a good idea register the Clockwork instance. Right before sending a response, we need to tell Clockwork to resolve and store metadata for current request. $clockwork->requestProcessed(); We also need to setup a Clockwork REST API endpoint. This endpoint is used by the Clockwork clients to load metadata for your application requests. By default Clockwork clients expect the data at /__clockwork URI. If your application uses a router, you can simply setup a GET route for this URI and pass rest of the URL to Clockwork. $router->get('/__clockwork/{request:.+}', function ($request) { $clockwork = Clockwork\Support\Vanilla\Clockwork::init(); return new JsonResponse($clockwork->getMetadata($request)); }}; In a very simple app without router you can use a separate script. In this case we will also need to tell Clockwork where to load the data from using the api option. // clockwork.php $clockwork = Clockwork\Support\Vanilla\Clockwork::init([ 'api' => '/clockwork.php?request=' ]); $clockwork->returnMetadata(); In the first example we used the getMetadata method which returns the metadata as an array, the returnMetadata will also json-ecncode the data, send it to output and set appropriate headers. PSR-7 applications Clockwork support in a PSR-7 application can be implemented as a middleware. return $clockwork->usePsrMessage($request, $response)->requestProcessed(); In this case Clockwork will use the data from the PSR-7 request and return the PSR-7 response extended with Clockwork headers. Configuration The vanilla Clockwork integration can be configured by passing a configuration array to the init method. $clockwork = Clockwork\Support\Vanilla\Clockwork::init([ 'storage' => 'sql', 'storage_database' => 'sqlite:' . __DIR__ . '/clockwork.sqlite' ]); You can find the full list of options with descriptions in the configuration file. You can also configure most options via environment variables, in this case you don't have to pass them to the init method. The clock helper Clockwork includes a clock global helper function providing easy access to Clockwork features from anywhere in the app. The clock helper is disabled by default in the vanilla integration, to enable the helper, use the register_helpers option. $clockwork = Clockwork\Support\Vanilla\Clockwork::init([ 'register_helpers' => true ]); clock('Log', 'something'); clock()->addDatabaseQuery('SELECT * FROM users WHERE id = 1', [], 10); Registering database queries There are many ways to make database queries in a vanilla PHP application. That's why unlike a framework integration, it's up to you to register the executed database queries. To do so, you can use the Clockwork addDatabaseQuery method in your database abstraction layer. If you don't have one, you can write a simple helper function or class for making queries, eg. this helper function for executing queries using PDO and logging them to Clockwork. function database_query($pdo, $query, $bindings) { $time = microtime(true); $stmt = $pdo->prepare($query); $stmt->execute($bindings); $results = $stmt->fetchAll(); clock()->addDatabaseQuery($query, $bindings, (microtime(true) - $time) * 1000); return $results; } You can use a similar approach to logging cache queries, events, sent emails, etc. see the source of the main Clockwork class for a list of all available methods.

Symfony Install the Clockwork library via Composer. $ composer require itsgoingd/clockwork Once Clockwork is installed, you need to register the Clockwork bundle in config/bundles.php : return [ ... Clockwork\Support\Symfony\ClockworkBundle::class => ['dev' => true] ] Clockwork routes also need to be registered in config/routes.yaml : clockwork: resource: '@ClockworkBundle/Resources/config/routing/clockwork.php' Clockwork uses the Symfony profiler as the data provider, make sure it is enabled: framework: profiler: { collect: true } Note: Symfony integration uses the built-in Symfony profiler. This means we can only show the same information as the Symfony Web Profiler, other Clockwork features are not available.

Slim Install the Clockwork library via Composer. $ composer require itsgoingd/clockwork Once Clockwork is installed, you'll need to add the Slim middleware to your app, specifying the path for the Clockwork metadata: $app = new Slim\App(...); $app->add(new Clockwork\Support\Slim\ClockworkMiddleware(__DIR__ . '/storage/clockwork')); Slim 2 is also supported: $app = new Slim(...); $app->add(new Clockwork\Support\Slim\Legacy\ClockworkMiddleware(__DIR__ . '/storage/clockwork'));

Features Collecting data The Clockwork server-side component collects and stores data about your application. Clockwork is only active when your app is in debug mode by default. You can choose to explicitly enable or disable Clockwork, or even set Clockwork to always collect data without exposing them for further analysis. We collect a whole bunch of useful data by default, but you can enable more features or disable features you don't need in the config file. Some features might allow for advanced options, eg. for database queries you can set a slow query threshold or enable detecting of duplicate (N+1) queries. Check out the config file to see all what Clockwork can do. New in Clockwork 4.1, artisan commands, queue jobs and tests can now also be collected, you need to enable this in the config file. Clockwork also collects stack traces for data like log messages or database queries. Last 10 frames of the trace are collected by default. You can change the frames limit or disable this feature in the configuration file. Artisan commands Clockwork supports collecting data about executed Artisan commands with optional support for collecting the command output. This is disabled by default and needs to be enabled in the config file. Queue jobs Clockwork supports collecting data about executed queue jobs with support for both the default Laravel queue worker and Laravel Horizon. This is disabled by default and needs to be enabled in the config file. Tests Clockwork supports collecting data about ran tests with support for the default Laravel PHPUnit testing setup. This is disabled by default and needs to be enabled in the config file. To collect data about ran tests, you also need to add and boot a Clockwork testing trait in your tests/TestCase.php : use Clockwork\Support\Laravel\Tests\UsesClockwork; abstract class TestCase extends BaseTestCase { use CreatesApplication, RefreshDatabase, UsesClockwork; protected function setUp() :void { parent::setUp(); $this->setUpClockwork(); } }

Viewing data Clockwork app is available as a browser extension: Chrome

Firefox The server-side component also includes a full copy of the Clockwork app available at your.app/__clockwork . This way you can use Clockwork anywhere, without installing extensions, yet we still don't inject anything to your application output. Web UI will show all executed requests, which is useful when the request is not made by browser, but for example a mobile application you are developing an API for.

Logging You can log any variable via the clock() helper, from a simple string to an array or object, even multiple values: clock(User::first(), auth()->user(), $username) 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())) If you want to specify a log level, you can use the long-form call: clock()->info("User {$username} logged in!") You can add a context to the log message via the second argument, serializer options can be passed in the context array: clock()->info("Trace this message!", [ 'trace' => true ]) You can use the performance option to make the log message appear in the performance tab. clock()->info("Api request {$method} {$uri}, took too long! ({$time})", [ 'performance' => true ]) All data logged using the standard Laravel log methods will also be collected.

Timeline Timeline gives you a visual representation of your application runtime. Clockwork will automatically add some default events, but you can also add custom ones. To add a custom event to the timeline, you'll need to start an event with an unique name and description first: clock()->startEvent('twitter-api-call', "Loading user's latest tweets via Twitter API") After executing the tracked block of code, you can end the event, using it's unique name. clock()->endEvent('twitter-api-call') Events that are not stopped explicitly will simply finish when the application runtime ends.

User data While you can log anything using the rich logging capabilities or add custom timeline events, sometimes your app has a specific data you'd like to be easily accessible for each request. With user data you can add custom data, shown as a new tab in the Clockwork app, formatted as a table or as counters (similar to performance tab). Let's say we are building an eshop app. 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: $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 €' ] ]); We are using static data for demonstration, in a real implementation the data would come from a database or session based on your cart implementation.

Advanced Authentication Clockwork collects a lot of sensitive data. Typically you will run Clockwork only in your local development environment where this is not an issue. In some cases though, you might have a shared development or staging server. For these situations Clockwork comes with a simple authentication using a single shared password. To use authentication, enable it and set a password in the Clockwork configuration file. The authentication system is extensible, to see how to add your own authentication methods see the "extending authentication" section. It is still not recommended to run Clockwork in production or environments that might contain sensitive customer data. Please make sure you understand the details of the authentication implementation if you plan to use it in a sensitive environment.

Metadata storage Clockwork stores the collected data in a persistent manner. The old data is automatically cleaned up after a specified cleanup interval, 30 days by default. By default we store the metadata in a flat JSON file storage, located at storage/clockwork . This is both simple and fast storage and doesn't require any particular PHP extensions. Clockwork also includes an SQL storage implementation. SQL storage works great with a simple Sqlite database, but also supports MySQL and PostgreSQL. This can also be useful in a case where you need to use the collected metadata outside of Clockwork, eg. you could build an admin UI showing all requests to your application. You can also extend Clockwork with your own metadata storage implementation, to learn how to do so, check out the "extending metadata storage".

Xdebug profiler While Clockwork provides a lot of performance metrics and profiling features like timeline events, finding the problematic spot in your application can still be hard. Xdebug is a PHP extension, which provides an advanced profiler, collecting metrics about every single function call. Clockwork comes with a full-featured Xdebug profiler UI, you can find it in the performance tab. The profiler UI will show you a breakdown of all function calls with their self and inclusive cost. You can toggle between execution time or memory usage metrics, exact or pecentual representation and of course the data is orderable and filterable. Setup Install the Xdebug extension via PECL (part of your PHP installation): $ pecl install xdebug Enable the PHP extension in your php.ini (location of php.ini and the xdebug extension path will depend on your operating system): zend_extension="/usr/local/php/modules/xdebug.so" Now we need to enable the Xdebug profiler itself. You could enable the profiling for all requests, but collecting Xdebug profiles slows down the response time dramatically. That's why it's a good idea to enable Xdebug profiling only for certain requests. To do so, add following setting to your php.ini and you will be able to toggle whether Xdebug profiles should be collected in Clockwork profiler UI itself: xdebug.profiler_enable_trigger=1 For more detailed information about installation and other awesome Xdebug features, check out the Xdebug website.

Extending Implementation This section describes how Clockwork internals work. While not needed for normal usage, this can be useful if you are planning on extending Clockwork with custom data sources, storage implementations, adding more in-depth support for your custom applications or unsupported frameworks or even writing a custom Clockwork client apps. Clockwork consists of two components: server-side library - responsible for collecting the data and exposing it to the clients

client application - responsible for presenting the collected data to the user The communication between the two components happens via a rest-like HTTP API using JSON metadata format. Server-side library The Clockwork server-side library consists of several components: DataSources - classes responsible for the metadata collection itself

Request - data objects for storing the metadata

Storage - classes responsible for persisting and retrieving the metadata

Support - various supporting files for frameworks and libraries, like service providers, middleware, etc. Clockwork also has a main Clockwork class that ties everything together and includes bunch of helper methods. While different Clockwork integrations work in different ways a typical usage looks like this: a new request is received by the application

main Clockwork class is instantiated, this automatically creates new Request instance for holding the metadata

one or more data sources are added to the Clockwork instance via $clockwork->addDataSource calls

calls a storage class is instantiated and set on the Clockwork instance via $clockwork->setStorage call

call application runs

$clockwork->resolveRequest is called, causing Request object to pass through resolve method on all configured data sources, each adding relevant data to the Request instance

is called, causing Request object to pass through method on all configured data sources, each adding relevant data to the Request instance $clockwork->storeRequest is called, persisting the Request object via set storage implementation

is called, persisting the Request object via set storage implementation X-Clockwork-Version and X-Clockwork-Id headers are set on the response Check out the "extending data sources" and "extending metadata storage" for information on writing your custom data sources and storage implementations. Metadata HTTP API The metadata HTTP API is the glue between the server-side data collecting library and the application presenting the data. By having a well specified rest-like API we can keep different versions of the Clockwork applications and the server-side library compatible and you could event write a fully custom Clockwork application compatible with the official server-side or vice-versa. /__clockwork/{id} is the main and most important API endpoint. Application requests metadata about request identified by a particular ID, server-side returns the metadata in a JSON format. While this is the only endpoint that is really required for the browser extensions to work and was the only endpoint available in the first version, there is a couple more endpoints required for various application features. /__clockwork/latest returns the metadata about the last executed request. Used in extension to show the last request when first time opened and required for web UI. /__clockwork/{id}|latest/next/{limit?} returns metadata for requests executed after request with specified ID or the latest request, with an optional limit. Required for the web UI. /__clockwork/{id}|latest/previous/{limit?} returns metadata for requests executed before request with specified ID or the latest request, with an optional limit. Used to load older requests in applications. Browser extension The browser extension checks HTTP responses for the X-Clockwork-Version and X-Clockwork-Id headers. The X-Clockwork-Version header contains the version of the server-side component, while the header is required, the content is not important and is used only for new version notifications. More important is the X-Clockwork-Id which contains the unique identifier for the current HTTP request. Once a request containing both of these headers is received, Clockwork retrieves the request metadata via a HTTP GET request to /__clockwork/{ID} . The metadata endpoint URI can be overridden via a X-Clockwork-Path header, if present, the request ID will be appended to the end of the header value. This endpoint should return the request metadata in the Clockwork metadata format. Web UI The web UI uses the same code as the browser extension, with only difference in the metadata retrieval. As we are not running as a browser extension and can't observe all executed HTTP requests, we use ajax polling instead. When opened, the application makes a request to the /__clockwork/latest endpoint to load the latest request. After that we poll the /__clockwork/{id}/next endpoint with the last request id to get all newer requests.

Data sources Data sources are a pattern for collecting the metadata in an extensible way in the Clockwork server-side library. Each data source collects data about a particular topic, eg. a PhpDataSource, LaravelDataSource, or DoctrineDataSource. Creating a new data source is as simple as creating a class implementing the Clockwork\DataSource\DataSourceInterface interface. Though instead of implementing the interface we recommend extending the Clockwork\DataSource\DataSource base class, which will make you compliant with future interface changes. You need to implement a single resolve(Request $request) method that will receive the Request data object and extends it with your custom data. For example, our application uses a custom session implementation, let's create a data source that adds the session data to Clockwork: use Clockwork\DataSource\DataSource; use Clockwork\Helpers\Request; class SessionDataSource extends DataSource { public function resolve(Request $request) { $request->session = session()->all(); } } To use the new data source we need to register it with the main Clockwork class: clock()->addDataSource(new SessionDataSource); For more inspiration take a look at the existing data sources included in Clockwork.

Metadata storage Clockwork stores the collected data in a persistent manner. By default we use a flat JSON file storage implementation and we also include an optional SQL storage implementation. To learn how to use included implementation see the "advanced metadata storage" section. While in most cases you will want to use one of the included options, you can write a custom one (eg. using Redis or unsupported SQL database). To create a storage implementation you will need to implement the Clockwork\Storage\StorageInterface interface, though it's recommended to extend the Clockwork\Storage\Storage base class instead. The interface contains a bunch of methods for reading requests, a save and a cleanup method. All read methods should return either single or an array of Clockwork\Helpers\Request instances. all() returns all stored requests

returns all stored requests find($id) returns a single request with specified ID or null

returns a single request with specified ID or null latest() returns a single latest request or null

returns a single latest request or null previous($id, $count = null) returns an array of requests received before specified ID, optionally limited to specified count

returns an array of requests received before specified ID, optionally limited to specified count next($id, $count = null) returns an array of requests received after specified ID, optionally limited to specified count

returns an array of requests received after specified ID, optionally limited to specified count store(Request $request) store the request

store the request cleanup() clean up old requests, the algorithm is up to you To use the custom storage implementation we need to set it on the main Clockwork class: clock()->setStorage(new RedisStorage); Feel free to take a look at existing storage implementations for inspiration.

Authentication The authentication in Clockwork works very simple. Each metadata request contains an authentication token, which is passed to the authenticator to decide whether we should return the metadata. If the Clockwork app receives a forbidden response, it will assume an authentication is required and asks for username, password or both as required by the authenticator. Submitting this form will make an authentication attempt on authenticator which will return a new authentication token when successful. To create an authenticator implementation you will need to implement the Clockwork\Authentication\AuthenticatorInterface interface. attempt(array $credentials) receives an array of credentials ( username , password or both), if the credentials are valid, returns an authentication token, returns null for invalid credentials

receives an array of credentials ( , or both), if the credentials are valid, returns an authentication token, returns null for invalid credentials check($token) receives an authentication token, returns true if the token is valid

receives an authentication token, returns true if the token is valid requires() returns an array of required credentials, this will be either AuthenticatorInterface::REQUIRES_USERNAME or AuthenticatorInterface::REQUIRES_PASSWORD , the Clockwork app will then show one or both fields To use the custom authenticator we need to set it on the main Clockwork class: clock()->setAuthenticator(new EloquentAuthenticator); Feel free to take a look at existing authenticator implementations for inspiration.