Added generic stopwatch collector and tests.

This commit is contained in:
Andrey Savchenko committed 2018-02-20 18:09:44 +02:00
1 parent 7020e84b2d
commit 420305143b
7 files changed
+215 -71

No files matched your search

+1 -1
View File
@@ -27,7 +27,7 @@ class Record_Provider implements ServiceProviderInterface, Bootable_Provider_Int
$pimple['collectors'] = function ( Plugin $laps ) { $pimple['collectors'] = function ( Plugin $laps ) {
return [ return [
'hook' => new Hook_Record_Collector( $laps['hook.events'], $laps['stopwatch'] ), 'hook' => new Hook_Record_Collector( $laps['stopwatch'], $laps['hook.events'] ),
'http' => new Http_Record_Collector( $laps['stopwatch'] ), 'http' => new Http_Record_Collector( $laps['stopwatch'] ),
'sql' => new Sql_Record_Collector(), 'sql' => new Sql_Record_Collector(),
]; ];
+12 -41
View File
@@ -4,34 +4,28 @@ namespace Rarst\Laps\Record;
use Rarst\Laps\Event\Hook_Event_Config_Interface; use Rarst\Laps\Event\Hook_Event_Config_Interface;
use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\Stopwatch\StopwatchEvent;
/** /**
* Processes events based on hooked starts and stops. * Processes events based on hooked starts and stops.
*/ */
class Hook_Record_Collector implements Record_Collector_Interface { class Hook_Record_Collector extends Stopwatch_Record_Collector {
/** @var Hook_Event_Config_Interface[] $event_configs */ /** @var Hook_Event_Config_Interface[] $event_configs */
protected $event_configs = []; protected $event_configs = [];
/** @var Stopwatch $stopwatch */
protected $stopwatch;
/** @var array $events */ /** @var array $events */
protected $events = []; protected $events = [];
/** /**
* @param array $event_configs Starts and stops configuration.
* @param Stopwatch $stopwatch Stopwatch instance. * @param Stopwatch $stopwatch Stopwatch instance.
* @param array $event_configs Starts and stops configuration.
*/ */
public function __construct( array $event_configs, Stopwatch $stopwatch ) { public function __construct( Stopwatch $stopwatch, array $event_configs ) {
$this->stopwatch = $stopwatch; parent::__construct( $stopwatch );
$this->stopwatch->start( 'Plugins Load', 'plugin' );
$this->start( 'Plugins Load', 'plugin' );
$this->add_events( $event_configs['core']->get_events() ); $this->add_events( $event_configs['core']->get_events() );
unset( $event_configs['core'] ); unset( $event_configs['core'] );
$this->event_configs = $event_configs; $this->event_configs = $event_configs;
@@ -48,9 +42,7 @@ class Hook_Record_Collector implements Record_Collector_Interface {
$this->events = array_merge( $this->events, $stops ); $this->events = array_merge( $this->events, $stops );
foreach ( $stops as $hook_name => $data ) { foreach ( $stops as $hook_name => $data ) {
foreach ( array_keys( $data ) as $priority ) { foreach ( array_keys( $data ) as $priority ) {
add_action( $hook_name, [ $this, 'tick' ], $priority ); add_action( $hook_name, [ $this, 'tick' ], $priority );
} }
} }
@@ -91,12 +83,12 @@ class Hook_Record_Collector implements Record_Collector_Interface {
'category' => null, 'category' => null,
] ); ] );
if ( 'stop' === $event['action'] && ! $this->stopwatch->isStarted( $event['event'] ) ) { if ( 'start' === $event['action'] ) {
return $input; $this->start( $event['event'], $event['category'] );
} else {
$this->stop( $event['event'] );
} }
$this->stopwatch->{$event['action']}( $event['event'], $event['category'] );
return $input; return $input;
} }
@@ -105,29 +97,8 @@ class Hook_Record_Collector implements Record_Collector_Interface {
*/ */
public function get_records() { public function get_records() {
if ( $this->stopwatch->isStarted( 'Toolbar' ) ) { $this->stopwatch->stop( 'Toolbar' );
$this->stopwatch->stop( 'Toolbar' );
}
$events = $this->stopwatch->getSectionEvents( '__root__' ); return parent::get_records();
foreach ( array_keys( $events ) as $name ) {
if ( $this->stopwatch->isStarted( $name ) ) {
unset( $events[ $name ] );
}
}
return array_map( [ $this, 'transform' ], array_keys( $events ), $events );
}
/**
* @param string $name Event name.
* @param StopwatchEvent $event Stopwatch event instance.
*
* @return Stopwatch_Record
*/
protected function transform( $name, StopwatchEvent $event ) {
return new Stopwatch_Record( $name, $event );
} }
} }
+4 -29
View File
@@ -3,22 +3,18 @@
namespace Rarst\Laps\Record; namespace Rarst\Laps\Record;
use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\Stopwatch\StopwatchEvent;
/** /**
* Captures time of network requests made with HTTP API. * Captures time of network requests made with HTTP API.
*/ */
class Http_Record_Collector implements Record_Collector_Interface { class Http_Record_Collector extends Stopwatch_Record_Collector {
/** @var Stopwatch $stopwatch */
protected $stopwatch;
/** /**
* @param Stopwatch $stopwatch Stopwatch instance. * @param Stopwatch $stopwatch Stopwatch instance.
*/ */
public function __construct( Stopwatch $stopwatch ) { public function __construct( Stopwatch $stopwatch ) {
$this->stopwatch = $stopwatch; parent::__construct( $stopwatch );
add_action( 'pre_http_request', [ $this, 'pre_http_request' ], 10, 3 ); add_action( 'pre_http_request', [ $this, 'pre_http_request' ], 10, 3 );
add_action( 'http_api_debug', [ $this, 'http_api_debug' ], 10, 5 ); add_action( 'http_api_debug', [ $this, 'http_api_debug' ], 10, 5 );
@@ -35,7 +31,7 @@ class Http_Record_Collector implements Record_Collector_Interface {
*/ */
public function pre_http_request( $false, $args, $url ) { public function pre_http_request( $false, $args, $url ) {
$this->stopwatch->start( $url, 'http' ); $this->start( $url, 'http' );
return $false; return $false;
} }
@@ -55,29 +51,8 @@ class Http_Record_Collector implements Record_Collector_Interface {
*/ */
public function http_api_debug( $response, $type, $class, $args, $url ) { public function http_api_debug( $response, $type, $class, $args, $url ) {
$this->stopwatch->stop( $url ); $this->stop( $url );
return $response; return $response;
} }
/**
* @return Stopwatch_Record[]
*/
public function get_records() {
$events = $this->stopwatch->getSectionEvents( '__root__' );
return array_map( [ $this, 'transform' ], array_keys( $events ), $events );
}
/**
* @param string $name Event name.
* @param StopwatchEvent $event Stopwatch event instance.
*
* @return Stopwatch_Record
*/
protected function transform( $name, StopwatchEvent $event ) {
return new Stopwatch_Record( $name, $event );
}
} }
+73
View File
@@ -0,0 +1,73 @@
<?php
namespace Rarst\Laps\Record;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\Stopwatch\StopwatchEvent;
/**
* Generic Stopwatch–based collector. Can be used by itself or extended.
*/
class Stopwatch_Record_Collector implements Record_Collector_Interface {
/** @var Stopwatch $stopwatch */
protected $stopwatch;
/**
* @param Stopwatch $stopwatch Stopwatch instance.
*/
public function __construct( Stopwatch $stopwatch ) {
$this->stopwatch = $stopwatch;
}
/**
* @param string $name The event name.
* @param string $category The event category.
*
* @return StopwatchEvent
*/
public function start( $name, $category = null ) {
return $this->stopwatch->start( $name, $category );
}
/**
* @param string $name The event name.
*
* @return bool|StopwatchEvent
*/
public function stop( $name ) {
if ( $this->stopwatch->isStarted( $name ) ) {
return $this->stopwatch->stop( $name );
}
return false;
}
/**
* @return Stopwatch_Record[]
*/
public function get_records() {
$events = $this->stopwatch->getSectionEvents( '__root__' );
foreach ( array_keys( $events ) as $name ) {
if ( $this->stopwatch->isStarted( $name ) ) {
unset( $events[ $name ] );
}
}
return array_map( [ $this, 'transform' ], array_keys( $events ), $events );
}
/**
* @param string $name Event name.
* @param StopwatchEvent $event Stopwatch event instance.
*
* @return Stopwatch_Record
*/
protected function transform( $name, StopwatchEvent $event ) {
return new Stopwatch_Record( $name, $event );
}
}
+46
View File
@@ -0,0 +1,46 @@
<?php
namespace Rarst\Laps\Tests\Record;
use Brain\Monkey\Functions;
use Rarst\Laps\Event\Core_Events;
use Rarst\Laps\Record\Hook_Record_Collector;
use Rarst\Laps\Tests\LapsTestCase;
use Symfony\Component\Stopwatch\Stopwatch;
class HookTest extends LapsTestCase {
public function testCollector() {
$stopwatch = new Stopwatch();
$collector = new Hook_Record_Collector( $stopwatch, [ 'core' => new Core_Events() ] );
$this->assertTrue( $stopwatch->isStarted( 'Plugins Load' ) );
$this->assertTrue( has_action( 'after_setup_theme', [ $collector, 'after_setup_theme' ] ) );
$collector->after_setup_theme();
Functions\expect( 'current_filter' )->once()->andReturn( 'plugins_loaded' );
Functions\expect( 'wp_parse_args' )->once()->andReturnFirstArg();
global $wp_filter;
$wp_hook = $this->getMockBuilder( 'WP_Hook' )
->allowMockingUnknownTypes()
->setMethods( [ 'current_priority' ] )
->getMock();
$wp_hook->method( 'current_priority' )->willReturn( - 2 );
$wp_filter['plugins_loaded'] = $wp_hook;
$collector->tick();
$this->assertFalse( $stopwatch->isStarted( 'Plugins Load' ) );
$stopwatch->start( 'Toolbar' );
$collector->get_records();
$this->assertFalse( $stopwatch->isStarted( 'Toolbar' ) );
}
}
+28
View File
@@ -0,0 +1,28 @@
<?php
namespace Rarst\Laps\Tests\Record;
use Rarst\Laps\Record\Http_Record_Collector;
use Rarst\Laps\Tests\LapsTestCase;
use Symfony\Component\Stopwatch\Stopwatch;
class HttpTest extends LapsTestCase {
public function testCollector() {
$stopwatch = new Stopwatch();
$url = 'https://example.com/';
$collector = new Http_Record_Collector( $stopwatch );
$this->assertTrue( has_action( 'pre_http_request', [ $collector, 'pre_http_request' ] ) );
$this->assertTrue( has_action( 'http_api_debug', [ $collector, 'http_api_debug' ] ) );
$collector->pre_http_request( false, [], $url );
$this->assertTrue( $stopwatch->isStarted( $url ) );
$collector->http_api_debug( [], '', new \stdClass(), [], $url );
$this->assertFalse( $stopwatch->isStarted( $url ) );
}
}
+51
View File
@@ -0,0 +1,51 @@
<?php
namespace Rarst\Laps\Tests\Record;
use Rarst\Laps\Record\Stopwatch_Record;
use Rarst\Laps\Record\Stopwatch_Record_Collector;
use Rarst\Laps\Tests\LapsTestCase;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\Stopwatch\StopwatchEvent;
class StopwatchTest extends LapsTestCase {
/**
* @covers \Rarst\Laps\Record\Stopwatch_Record_Collector
*/
public function testCollector() {
$collector = new Stopwatch_Record_Collector( new Stopwatch() );
$collector->start( 'Event', 'info' );
$collector->start( 'Not stopped', 'info' );
$event = $collector->stop( 'Event' );
$this->assertFalse( $collector->stop( 'Not event' ) );
$records = $collector->get_records();
$this->assertInternalType( 'array', $records );
$this->assertCount( 1, $records );
$this->assertInstanceOf( Stopwatch_Record::class, $records[0] );
return $event;
}
/**
* @depends testCollector
* @covers \Rarst\Laps\Record\Stopwatch_Record
*
* @param StopwatchEvent $event Event instance.
*/
public function testRecord( StopwatchEvent $event ) {
$record = new Stopwatch_Record( 'Event', $event );
$this->assertEquals( 'Event', $record->get_name() );
$this->assertEquals( 'info', $record->get_category() );
$this->assertEquals( $event->getOrigin(), $record->get_origin() );
$this->assertEquals( $event->getDuration(), $record->get_duration() );
$this->assertContains( 'Event', $record->get_description() );
}
}