From 3dd3d03a612b9c6b9782dbff0fe72b05954a7ebd Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Sat, 4 Nov 2023 19:52:46 -0400 Subject: [PATCH] feat: improves detail --- src/Blocks/NetworkDuration.php | 63 ----------- src/Blocks/ResponseDuration.php | 61 ----------- src/Blocks/ServerDuration.php | 57 ---------- src/Blocks/SuccessRate.php | 51 --------- src/Expectation.php | 16 --- src/ResultPrinters/Blocks.php | 183 -------------------------------- src/ResultPrinters/Detail.php | 77 ++++++++------ src/ResultPrinters/Progress.php | 22 ++-- src/Run.php | 10 +- src/Session.php | 18 ++++ 10 files changed, 81 insertions(+), 477 deletions(-) delete mode 100644 src/Blocks/NetworkDuration.php delete mode 100644 src/Blocks/ResponseDuration.php delete mode 100644 src/Blocks/ServerDuration.php delete mode 100644 src/Blocks/SuccessRate.php delete mode 100644 src/Expectation.php delete mode 100644 src/ResultPrinters/Blocks.php diff --git a/src/Blocks/NetworkDuration.php b/src/Blocks/NetworkDuration.php deleted file mode 100644 index 723b308..0000000 --- a/src/Blocks/NetworkDuration.php +++ /dev/null @@ -1,63 +0,0 @@ -result->toArray(); - - $duration = $array['metrics']['http_req_connecting']['values']['avg'] - + $array['metrics']['http_req_tls_handshaking']['values']['avg'] - + $array['metrics']['http_req_duration']['values']['avg'] - - $array['metrics']['http_req_waiting']['values']['avg']; - - $duration = sprintf('%4.2f ms', $duration); - - if (strlen($duration) < 9) { - $duration = str_pad($duration, 9, ' ', STR_PAD_BOTH); - } - - return $duration; - } - - /** - * Gets the block color. - */ - public function color(): string - { - $array = $this->result->toArray(); - - $duration = $array['metrics']['http_req_connecting']['values']['avg'] - + $array['metrics']['http_req_tls_handshaking']['values']['avg'] - + $array['metrics']['http_req_duration']['values']['avg'] - - $array['metrics']['http_req_waiting']['values']['avg']; - - return match (true) { - $duration < 100 => 'green', - $duration < 200 => 'yellow', - default => 'red', - }; - } -} diff --git a/src/Blocks/ResponseDuration.php b/src/Blocks/ResponseDuration.php deleted file mode 100644 index 250f3df..0000000 --- a/src/Blocks/ResponseDuration.php +++ /dev/null @@ -1,61 +0,0 @@ -result->toArray(); - - $duration = $array['metrics']['http_req_connecting']['values']['avg'] - + $array['metrics']['http_req_tls_handshaking']['values']['avg'] - + $array['metrics']['http_req_duration']['values']['avg']; - - $duration = sprintf('%4.2f ms', $duration); - - if (strlen($duration) < 9) { - $duration = str_pad($duration, 9, ' ', STR_PAD_BOTH); - } - - return $duration; - } - - /** - * Gets the block color. - */ - public function color(): string - { - $array = $this->result->toArray(); - - $duration = $array['metrics']['http_req_connecting']['values']['avg'] - + $array['metrics']['http_req_tls_handshaking']['values']['avg'] - + $array['metrics']['http_req_duration']['values']['avg']; - - return match (true) { - $duration < 200 => 'green', - $duration < 400 => 'yellow', - default => 'red', - }; - } -} diff --git a/src/Blocks/ServerDuration.php b/src/Blocks/ServerDuration.php deleted file mode 100644 index 6222821..0000000 --- a/src/Blocks/ServerDuration.php +++ /dev/null @@ -1,57 +0,0 @@ -result->toArray(); - - $duration = $array['metrics']['http_req_waiting']['values']['avg']; - - $duration = sprintf('%4.2f ms', $duration); - - if (strlen($duration) < 9) { - $duration = str_pad($duration, 9, ' ', STR_PAD_BOTH); - } - - return $duration; - } - - /** - * Gets the block color. - */ - public function color(): string - { - $array = $this->result->toArray(); - - $duration = $array['metrics']['http_req_waiting']['values']['avg']; - - return match (true) { - $duration < 100 => 'green', - $duration < 200 => 'yellow', - default => 'red', - }; - } -} diff --git a/src/Blocks/SuccessRate.php b/src/Blocks/SuccessRate.php deleted file mode 100644 index a805804..0000000 --- a/src/Blocks/SuccessRate.php +++ /dev/null @@ -1,51 +0,0 @@ -result->toArray(); - - $percentage = (float) ($array['metrics']['http_req_failed']['values']['fails'] * 100 / $array['metrics']['http_reqs']['values']['count']); - - if ($percentage === 100.0) { - return '100 %'; - } - - return sprintf('%4.1f %%', $percentage); - } - - /** - * Gets the block color. - */ - public function color(): string - { - $array = $this->result->toArray(); - - return $array['metrics']['http_req_failed']['values']['fails'] === $array['metrics']['http_reqs']['values']['count'] - ? 'green' - : 'red'; - } -} diff --git a/src/Expectation.php b/src/Expectation.php deleted file mode 100644 index 3748ae5..0000000 --- a/src/Expectation.php +++ /dev/null @@ -1,16 +0,0 @@ -%block_size% - %success_rate% - <%success_rate_color%>%block_size% - EOD; - - private const RESPONSE_DURATION = <<<'EOD' - <%response_time_color%>%block_size% - %response_time% - <%response_time_color%>%block_size% - EOD; - - private const NETWORK_DURATION = <<<'EOD' - <%network_color%>%block_size% - %network% - <%network_color%>%block_size% - EOD; - - private const SERVER_DURATION = <<<'EOD' - <%server_duration_color%>%block_size% - %server_duration% - <%server_duration_color%>%block_size% - EOD; - - public function print(Result $result): void - { - render(<<<'HTML' -
- - -
- HTML); - - $successRate = new SuccessRate($result); - $responseDuration = new ResponseDuration($result); - $networkDuration = new NetworkDuration($result); - $serverDuration = new ServerDuration($result); - - $templates = [ - '%success_rate%' => $successRate->value(), - '%success_rate_color%' => "bg={$successRate->color()}", - '%response_time%' => $responseDuration->value(), - '%response_time_color%' => "bg={$responseDuration->color()}", - '%network%' => $networkDuration->value(), - '%network_color%' => "bg={$networkDuration->color()}", - '%server_duration%' => $serverDuration->value(), - '%server_duration_color%' => "bg={$serverDuration->color()}", - '%subtitle%' => 'options=bold', - ]; - $disposition = self::ALL_BLOCKS_IN_ROW; - $spaceWidth = $this->getSpaceWidth(terminal()->width(), self::BLOCK_SIZE, $disposition); - - if (terminal()->width() < ((self::BLOCK_SIZE * $disposition) + 5 * $spaceWidth)) { - $disposition = self::TWO_BLOCKS_IN_ROW; - $spaceWidth = $this->getSpaceWidth(terminal()->width(), self::BLOCK_SIZE, $disposition); - } - - $templates = [...$templates, '%block_size%' => str_pad('', self::BLOCK_SIZE)]; - - $styleDefinition = clone Table::getStyleDefinition('compact'); - - $styleDefinition->setVerticalBorderChars( - str_pad('', (int) floor($spaceWidth / 2)), // outside - '' // inside - ); - - $styleDefinition->setPadType(STR_PAD_BOTH); - $styleDefinition->setCellRowContentFormat('%s'); - - $table = new Table(new ConsoleOutput()); - $table->setStyle($styleDefinition); - - $table->setColumnWidth(0, self::BLOCK_SIZE + $spaceWidth); - $table->setColumnWidth(1, self::BLOCK_SIZE + $spaceWidth); - $table->setColumnWidth(2, self::BLOCK_SIZE + $spaceWidth); - $table->setColumnWidth(3, self::BLOCK_SIZE + $spaceWidth); - - if ($disposition === self::ALL_BLOCKS_IN_ROW) { - $table->setRows([ - [ - strtr(self::SUCCESS_RATE, $templates), - strtr(self::RESPONSE_DURATION, $templates), - strtr(self::NETWORK_DURATION, $templates), - strtr(self::SERVER_DURATION, $templates), - ], - ['', '', '', ''], - [ - strtr('<%subtitle%> Success Rate ', $templates), - strtr('<%subtitle%> Response ', $templates), - strtr('<%subtitle%> Network ', $templates), - strtr('<%subtitle%> Server ', $templates), - ], - ]); - } - - if ($disposition === self::TWO_BLOCKS_IN_ROW) { - $table->setRows([ - [ - strtr(self::SUCCESS_RATE, $templates), - strtr(self::RESPONSE_DURATION, $templates), - ], - ['', ''], - [ - strtr('<%subtitle%> Success Rate ', $templates), - strtr('<%subtitle%> Response ', $templates), - ], - ['', ''], - [ - strtr(self::NETWORK_DURATION, $templates), - strtr(self::SERVER_DURATION, $templates), - ], - ['', ''], - [ - strtr('<%subtitle%> Network ', $templates), - strtr('<%subtitle%> Server ', $templates), - ], - ]); - } - - $table->render(); - - render(<<<'HTML' -
- - 0-49 - - 50-89 - - 90-100 -
- HTML); - } - - /** - * Total width of terminal - block size * disposition (4 or 2) / number of space block. - */ - private function getSpaceWidth(int $totalWidth, int $blockSize, int $disposition): int - { - $spaceWidth = (int) floor(($totalWidth - $blockSize * $disposition) / ($disposition + 1)); - - if ($spaceWidth > self::MAX_SPACEWIDTH) { - $spaceWidth = self::MAX_SPACEWIDTH; - } - - if ($spaceWidth < self::MIN_SPACEWIDTH) { - return self::MIN_SPACEWIDTH; - } - - return $spaceWidth; - } -} diff --git a/src/ResultPrinters/Detail.php b/src/ResultPrinters/Detail.php index 19ecc53..46b17c7 100644 --- a/src/ResultPrinters/Detail.php +++ b/src/ResultPrinters/Detail.php @@ -18,6 +18,13 @@ */ public function print(Result $result): void { + render(<<<'HTML' +
+ Result + +
+ HTML); + /** * data_received..................: 22 kB 5.7 kB/s * data_sent......................: 742 B 198 B/s @@ -41,28 +48,30 @@ public function print(Result $result): void $this->overview($result, $metrics); $this->server($metrics); $this->network($metrics); - } - /** - * Prints the overview's detail. - */ - private function overview(Result $result, array $metrics): void - { render(<<<'HTML' -
- +
+ - + - - - 50-89 - - 90-100 + Critical + + Poor + + Ok + + Excellent
); HTML); + } + /** + * Prints the overview's detail. + */ + private function overview(Result $result, array $metrics): void + { $testRunDuration = $result->testRunDuration(); $testRunDuration = sprintf('%4.2f', $testRunDuration / 1000); @@ -70,10 +79,10 @@ private function overview(Result $result, array $metrics): void $requestsTotal = $metrics['http_reqs']['values']['count']; $requestsRate = round($metrics['http_reqs']['values']['rate'], 2); - $testRunConcurrentUsers = $result->testRunConcurrentUsers(); + $result->testRunConcurrentUsers(); $this->twoColumnDetail('Total Requests', <<$requestsRate reqs/second │ $testRunConcurrentUsers concurrent users + $requestsRate reqs/second $requestsTotal requests HTML); @@ -92,15 +101,17 @@ private function overview(Result $result, array $metrics): void + $metrics['http_req_duration']['values']['avg']; $responseDurationColor = match (true) { - $responseDuration < 200 => 'green', - $responseDuration < 400 => 'yellow', - default => 'red', + $responseDuration === 0.0 => '', + $responseDuration < 200.0 => 'text-green', + $responseDuration < 400.0 => 'text-yellow', + $responseDuration < 800.0 => 'text-orange', + default => 'text-red', }; $responseDuration = sprintf('%4.2f', $responseDuration); $this->twoColumnDetail('Response Duration', <<$responseDuration ms + $responseDuration ms HTML); } @@ -119,18 +130,20 @@ private function network(array $metrics): void - $metrics['http_req_waiting']['values']['avg']; $responseNetworkDurationPercentage = $responseDuration > 0.00 ? round($responseNetworkDuration * 100 / $responseDuration, 2) : 0.00; $responseNetworkDurationColor = match (true) { - $responseNetworkDuration < 100 => 'green', - $responseNetworkDuration < 200 => 'yellow', - default => 'red', + $responseNetworkDuration === 0.0 => '', + $responseNetworkDuration < 100.0 => 'text-green', + $responseNetworkDuration < 200.0 => 'text-yellow', + $responseNetworkDuration < 400.0 => 'text-orange', + default => 'text-red', }; $responseNetworkDuration = sprintf('%4.2f', $responseNetworkDuration); $this->twoColumnDetail(<<├Network + Network $responseNetworkDurationPercentage % HTML, <<$responseNetworkDuration ms + $responseNetworkDuration ms HTML); $tlsHandshakingTime = $metrics['http_req_tls_handshaking']['values']['avg']; @@ -151,7 +164,7 @@ private function network(array $metrics): void 'Upload' => "$uploadTime ms", 'Download' => "$downloadTime ms", ] as $title => $value) { - $this->twoColumnDetail('│ ├'.$title, $value); + $this->twoColumnDetail(''.$title, $value); } } @@ -165,19 +178,21 @@ private function server(array $metrics): void + $metrics['http_req_duration']['values']['avg']; $responseServerDuration = $metrics['http_req_waiting']['values']['avg']; $responseServerDurationColor = match (true) { - $responseDuration < 100 => 'green', - $responseDuration < 200 => 'yellow', - default => 'red', + $responseServerDuration === 0.0 => '', + $responseServerDuration < 100.0 => 'text-green', + $responseServerDuration < 200.0 => 'text-yellow', + $responseServerDuration < 400.0 => 'text-orange', + default => 'text-red', }; $responseServerDurationPercentage = $responseDuration > 0.00 ? round($responseServerDuration * 100 / $responseDuration, 2) : 0.00; $responseServerDuration = sprintf('%4.2f', $responseServerDuration); $this->twoColumnDetail(<<├Server + Server $responseServerDurationPercentage % HTML, <<$responseServerDuration ms + $responseServerDuration ms HTML); } diff --git a/src/ResultPrinters/Progress.php b/src/ResultPrinters/Progress.php index 43be3e2..332fc96 100644 --- a/src/ResultPrinters/Progress.php +++ b/src/ResultPrinters/Progress.php @@ -29,14 +29,16 @@ public function __construct(private Process $process, private Session $session, */ public function tail(): void { - $date = date('H:i:s'); $domain = $this->url->domain(); + $concurrentRequests = $this->session->concurrentRequests(); + $duration = $this->session->duration(); + render(<< - $date - - Stress testing $domain +
+ Stress testing $domain + + {$concurrentRequests} concurrent requests for {$duration} seconds
HTML); @@ -69,7 +71,7 @@ public function tail(): void foreach ($lines as $line) { if (str_starts_with($line, '{"metric":"http_req_duration","type":"Point"')) { /** @var array{data: array{time: string, value: float}}|null $point */ - $point = json_decode($line, true); + $point = json_decode($line, true, 512, JSON_THROW_ON_ERROR); if (is_array($point)) { $currentTime = substr($point['data']['time'], 0, 19); @@ -115,13 +117,13 @@ private function printCurrentPoints(array $points): void $greenDots = (int) (($average * $width) / $maxResponseTime); - $greenDots = str_repeat('█', $greenDots); + $greenDots = str_repeat('▉', $greenDots); render(<< +
- {$time}│ - $greenDots + {$time} + $greenDots {$average}ms diff --git a/src/Run.php b/src/Run.php index d11a044..0eed55d 100644 --- a/src/Run.php +++ b/src/Run.php @@ -5,7 +5,6 @@ namespace Pest\Stressless; use Pest\Exceptions\ShouldNotHappen; -use Pest\Stressless\ResultPrinters\Blocks; use Pest\Stressless\ResultPrinters\Detail; use Pest\Stressless\ResultPrinters\Progress; use Pest\Stressless\ValueObjects\Binary; @@ -34,9 +33,14 @@ public function __construct(private Url $url, private array $options, private bo */ public function start(): Result { + $concurrentRequests = (int) $this->options['stages'][1]['target']; + $duration = (int) $this->options['stages'][1]['duration']; + $session = new Session( $basePath = dirname(__DIR__), uniqid('pest', true), + $concurrentRequests, + $duration, ); $process = new Process([ @@ -70,10 +74,6 @@ public function start(): Result $result = new Result($metrics); // @phpstan-ignore-line if ($this->verbose) { - $blocks = new Blocks(); - - $blocks->print($result); - $detail = new Detail(); $detail->print($result); diff --git a/src/Session.php b/src/Session.php index 01e6ca4..6f74b97 100644 --- a/src/Session.php +++ b/src/Session.php @@ -17,6 +17,8 @@ public function __construct( private string $basePath, private string $id, + private int $concurrentRequests, + private int $duration, ) { // } @@ -50,6 +52,22 @@ public function clean(): void } } + /** + * Gets the number of concurrent requests. + */ + public function concurrentRequests(): int + { + return $this->concurrentRequests; + } + + /** + * Gets the duration of the run. + */ + public function duration(): int + { + return $this->duration; + } + /** * Destroys the session instance. */