Skip to content
This repository has been archived by the owner on Nov 29, 2021. It is now read-only.

Allow manually Transaction start time #52

Merged
merged 4 commits into from
Feb 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/Agent.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,16 +129,19 @@ public function __construct(array $config, array $sharedContext = [], EventFacto
*
* @return Transaction
*/
public function startTransaction(string $name, array $context = []): Transaction
public function startTransaction(string $name, array $context = [], float $start = null): Transaction
{
// Create and Store Transaction
$this->transactionsStore->register(
$this->eventFactory->createTransaction($name, array_replace_recursive($this->sharedContext, $context))
$this->eventFactory->createTransaction($name, array_replace_recursive($this->sharedContext, $context), $start)
);

// Start the Transaction
$transaction = $this->transactionsStore->fetch($name);
$transaction->start();

if (null === $start) {
$transaction->start();
}

return $transaction;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Events/DefaultEventFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public function createError(\Throwable $throwable, array $contexts): Error
/**
* {@inheritdoc}
*/
public function createTransaction(string $name, array $contexts): Transaction
public function createTransaction(string $name, array $contexts, float $start = null): Transaction
{
return new Transaction($name, $contexts);
return new Transaction($name, $contexts, $start);
}
}
2 changes: 1 addition & 1 deletion src/Events/EventFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ public function createError(\Throwable $throwable, array $contexts): Error;
* @param string $name
* @param array $contexts
*/
public function createTransaction(string $name, array $contexts): Transaction;
public function createTransaction(string $name, array $contexts, float $start = null): Transaction;
}
4 changes: 2 additions & 2 deletions src/Events/Transaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ class Transaction extends EventBean implements \JsonSerializable
* @param string $name
* @param array $contexts
*/
public function __construct(string $name, array $contexts)
public function __construct(string $name, array $contexts, $start = null)
{
parent::__construct($contexts);
$this->setTransactionName($name);
$this->timer = new Timer();
$this->timer = new Timer($start);
}

/**
Expand Down
13 changes: 13 additions & 0 deletions src/Exception/Timer/AlreadyRunningException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
namespace PhilKra\Exception\Timer;

/**
* Trying to stop a Timer that is already running
*/
class AlreadyRunningException extends \Exception {

public function __construct( string $message = '', int $code = 0, \Throwable $previous = NULL ) {
parent::__construct( 'Can\'t start a timer which is already running.', $code, $previous );
}

}
11 changes: 11 additions & 0 deletions src/Helper/Timer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PhilKra\Helper;

use PhilKra\Exception\Timer\AlreadyRunningException;
use PhilKra\Exception\Timer\NotStartedException;
use PhilKra\Exception\Timer\NotStoppedException;

Expand All @@ -24,13 +25,23 @@ class Timer
*/
private $stoppedOn = null;

public function __construct(float $startTime = null)
{
$this->startedOn = $startTime;
}

/**
* Start the Timer
*
* @return void
* @throws AlreadyRunningException
*/
public function start()
{
if (null !== $this->startedOn) {
throw new AlreadyRunningException();
}

$this->startedOn = microtime(true);
}

Expand Down
26 changes: 26 additions & 0 deletions tests/AgentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,32 @@ public function testStartAndStopATransaction() {
$this->assertNotEmpty( $summary['backtrace'] );
}

/**
* @covers \PhilKra\Agent::__construct
* @covers \PhilKra\Agent::startTransaction
* @covers \PhilKra\Agent::stopTransaction
* @covers \PhilKra\Agent::getTransaction
*/
public function testStartAndStopATransactionWithExplicitStart() {
$agent = new Agent( [ 'appName' => 'phpunit_1' ] );

// Create a Transaction, wait and Stop it
$name = 'trx';
$agent->startTransaction( $name, [], microtime(true) - 1);
usleep( 500 * 1000 ); // sleep milliseconds
$agent->stopTransaction( $name );

// Transaction Summary must be populated
$summary = $agent->getTransaction( $name )->getSummary();

$this->assertArrayHasKey( 'duration', $summary );
$this->assertArrayHasKey( 'backtrace', $summary );

// Expect duration in milliseconds
$this->assertDurationIsWithinThreshold(1500, $summary['duration'], 150);
$this->assertNotEmpty( $summary['backtrace'] );
}

/**
* @depends testStartAndStopATransaction
*
Expand Down
28 changes: 28 additions & 0 deletions tests/Helper/TimerTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace PhilKra\Tests\Helper;

use PhilKra\Exception\Timer\AlreadyRunningException;
use \PhilKra\Helper\Timer;
use PhilKra\Tests\TestCase;

Expand Down Expand Up @@ -92,4 +93,31 @@ public function testCannotBeStoppedWithoutStart() {
$timer->stop();
}

/**
* @covers \PhilKra\Helper\Timer::start
* @covers \PhilKra\Helper\Timer::getDurationInMilliseconds
*/
public function testCanBeStartedWithExplicitStartTime() {
$timer = new Timer(microtime(true) - .5); // Start timer 500 milliseconds ago

usleep(500 * 1000); // Sleep for 500 milliseconds

$timer->stop();

$duration = $timer->getDurationInMilliseconds();

// Duration should be more than 1000 milliseconds
// sum of initial offset and sleep
$this->assertGreaterThanOrEqual(1000, $duration);
}

/**
* @covers \PhilKra\Helper\Timer::start
*/
public function testCannotBeStartedIfAlreadyRunning() {
$timer = new Timer(microtime(true));

$this->expectException(AlreadyRunningException::class);
$timer->start();
}
}
10 changes: 4 additions & 6 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@
abstract class TestCase extends \PHPUnit\Framework\TestCase
{

protected function assertDurationIsWithinThreshold(int $sleptMilliseconds, float $timedDuration)
protected function assertDurationIsWithinThreshold(int $expectedMilliseconds, float $timedDuration, float $maxOverhead = 10)
{
$this->assertGreaterThanOrEqual( $sleptMilliseconds, $timedDuration );
$this->assertGreaterThanOrEqual( $expectedMilliseconds, $timedDuration );

// Generally we should expect less than 1ms of overhead, but that is not guaranteed.
// 10ms should be enough unless the test system is really unresponsive.
$overhead = ($timedDuration - $sleptMilliseconds);
$this->assertLessThanOrEqual( 10, $overhead );
$overhead = ($timedDuration - $expectedMilliseconds);
$this->assertLessThanOrEqual( $maxOverhead, $overhead );
}

}