Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0131c92

Browse files
[Monolog] Use stream helper and test server:log command
1 parent 6d3d234 commit 0131c92

File tree

3 files changed

+1041
-42
lines changed

3 files changed

+1041
-42
lines changed

src/Symfony/Bridge/Monolog/Command/ServerLogCommand.php

Lines changed: 20 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
use Symfony\Component\Console\Attribute\AsCommand;
2121
use Symfony\Component\Console\Command\Command;
2222
use Symfony\Component\Console\Exception\LogicException;
23-
use Symfony\Component\Console\Exception\RuntimeException;
2423
use Symfony\Component\Console\Input\InputInterface;
2524
use Symfony\Component\Console\Input\InputOption;
2625
use Symfony\Component\Console\Output\OutputInterface;
@@ -34,7 +33,6 @@ class ServerLogCommand extends Command
3433
{
3534
private const BG_COLOR = ['black', 'blue', 'cyan', 'green', 'magenta', 'red', 'white', 'yellow'];
3635

37-
private ExpressionLanguage $el;
3836
private HandlerInterface $handler;
3937

4038
public function isEnabled(): bool
@@ -78,12 +76,13 @@ protected function configure(): void
7876

7977
protected function execute(InputInterface $input, OutputInterface $output): int
8078
{
79+
$el = null;
8180
$filter = $input->getOption('filter');
8281
if ($filter) {
8382
if (!class_exists(ExpressionLanguage::class)) {
8483
throw new LogicException('Package "symfony/expression-language" is required to use the "filter" option. Try running "composer require symfony/expression-language".');
8584
}
86-
$this->el = new ExpressionLanguage();
85+
$el = new ExpressionLanguage();
8786
}
8887

8988
$this->handler = new ConsoleHandler($output, true, [
@@ -101,49 +100,28 @@ protected function execute(InputInterface $input, OutputInterface $output): int
101100
$host = 'tcp://'.$host;
102101
}
103102

104-
if (!$socket = stream_socket_server($host, $errno, $errstr)) {
105-
throw new RuntimeException(sprintf('Server start failed on "%s": ', $host).$errstr.' '.$errno);
106-
}
107-
108-
foreach ($this->getLogs($socket) as $clientId => $message) {
109-
$record = unserialize(base64_decode($message));
103+
$streamHelper = $this->getHelper('stream');
104+
$streamHelper->listen(
105+
$input,
106+
$output,
107+
$host,
108+
function (int $clientId, string $message) use ($el, $filter, $output) {
109+
$record = unserialize(base64_decode($message));
110+
111+
// Impossible to decode the message, give up.
112+
if (false === $record) {
113+
return;
114+
}
110115

111-
// Impossible to decode the message, give up.
112-
if (false === $record) {
113-
continue;
114-
}
116+
if ($filter && !$el->evaluate($filter, $record)) {
117+
return;
118+
}
115119

116-
if ($filter && !$this->el->evaluate($filter, $record)) {
117-
continue;
120+
$this->displayLog($output, $clientId, $record);
118121
}
122+
);
119123

120-
$this->displayLog($output, $clientId, $record);
121-
}
122-
123-
return 0;
124-
}
125-
126-
private function getLogs($socket): iterable
127-
{
128-
$sockets = [(int) $socket => $socket];
129-
$write = [];
130-
131-
while (true) {
132-
$read = $sockets;
133-
stream_select($read, $write, $write, null);
134-
135-
foreach ($read as $stream) {
136-
if ($socket === $stream) {
137-
$stream = stream_socket_accept($socket);
138-
$sockets[(int) $stream] = $stream;
139-
} elseif (feof($stream)) {
140-
unset($sockets[(int) $stream]);
141-
fclose($stream);
142-
} else {
143-
yield (int) $stream => fgets($stream);
144-
}
145-
}
146-
}
124+
return Command::SUCCESS;
147125
}
148126

149127
private function displayLog(OutputInterface $output, int $clientId, array $record): void
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Monolog\Tests\Command;
13+
14+
use Monolog\Level;
15+
use Monolog\LogRecord;
16+
use PHPUnit\Framework\TestCase;
17+
use Symfony\Bridge\Monolog\Command\ServerLogCommand;
18+
use Symfony\Component\Console\Helper\HelperSet;
19+
use Symfony\Component\Console\Helper\StreamHelper;
20+
use Symfony\Component\Console\Tester\CommandTester;
21+
22+
class ServerLogCommandTest extends TestCase
23+
{
24+
public function testServerLogSuccess()
25+
{
26+
$command = $this->createCommand();
27+
$commandTester = new CommandTester($command);
28+
29+
$record = new LogRecord(
30+
new \DateTimeImmutable('2024-01-02 18:05'),
31+
'console',
32+
Level::Info,
33+
'test log command',
34+
);
35+
$recordFormatted = $record->toArray();
36+
$input = base64_encode(serialize($recordFormatted))."\n";
37+
38+
$commandTester->setInputs([$input]);
39+
40+
$commandTester->execute([]);
41+
42+
$commandTester->assertCommandIsSuccessful();
43+
44+
$output = $commandTester->getDisplay();
45+
$this->assertStringContainsString('18:05:00 INFO [console] test log command', $output);
46+
}
47+
48+
private function createCommand(): ServerLogCommand
49+
{
50+
$command = new ServerLogCommand();
51+
$command->setHelperSet(new HelperSet([new StreamHelper()]));
52+
53+
return $command;
54+
}
55+
}

0 commit comments

Comments
 (0)