Skip to content

Commit ce67e41

Browse files
committed
feature symfony#57426 [Messenger] Add --format option to the messenger:stats command (xvilo)
This PR was squashed before being merged into the 7.2 branch. Discussion ---------- [Messenger] Add `--format` option to the `messenger:stats` command | Q | A | ------------- | --- | Branch? | 7.2 | Bug fix? | no | New feature? | yes <!-- please update src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Issues | Fix symfony#48583 <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead --> | License | MIT As requested in symfony#48583 add a way to output different in formats for `messenger:stats` command. This can be more easily used in, for example, `jq` or with external automations/scripts and such. Considerations I made: - To not, yet, make different classes for the output. In case a new output format is added this might be handy. - To not use an enum for output format, do we want this? - To ignore warnings for now, except for the `uncountable_transports`. If we want to warning in there, what format? Commits ------- 0e9f458 [Messenger] Add `--format` option to the `messenger:stats` command
2 parents cd255c3 + 0e9f458 commit ce67e41

File tree

3 files changed

+103
-2
lines changed

3 files changed

+103
-2
lines changed

src/Symfony/Component/Messenger/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.2
5+
---
6+
7+
* Add `--format` option to the `messenger:stats` command
8+
49
7.1
510
---
611

src/Symfony/Component/Messenger/Command/StatsCommand.php

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
use Symfony\Component\Console\Command\Command;
1717
use Symfony\Component\Console\Input\InputArgument;
1818
use Symfony\Component\Console\Input\InputInterface;
19+
use Symfony\Component\Console\Input\InputOption;
1920
use Symfony\Component\Console\Output\ConsoleOutputInterface;
2021
use Symfony\Component\Console\Output\OutputInterface;
2122
use Symfony\Component\Console\Style\SymfonyStyle;
23+
use Symfony\Component\Messenger\Exception\InvalidArgumentException;
2224
use Symfony\Component\Messenger\Transport\Receiver\MessageCountAwareInterface;
2325

2426
/**
@@ -36,8 +38,10 @@ public function __construct(
3638

3739
protected function configure(): void
3840
{
41+
$outputFormats = implode(', ', $this->getAvailableFormatOptions());
3942
$this
4043
->addArgument('transport_names', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'List of transports\' names')
44+
->addOption('format', '', InputOption::VALUE_REQUIRED, 'The output format, e.g.: '.$outputFormats, 'text', $this->getAvailableFormatOptions())
4145
->setHelp(<<<EOF
4246
The <info>%command.name%</info> command counts the messages for all the transports:
4347
@@ -46,6 +50,11 @@ protected function configure(): void
4650
Or specific transports only:
4751
4852
<info>php %command.full_name% <transportNames></info>
53+
54+
The <info>--format</info> option specifies the format of command output,
55+
these are "{$outputFormats}".
56+
57+
<info>php %command.full_name% --format=json</info>
4958
EOF
5059
)
5160
;
@@ -55,6 +64,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5564
{
5665
$io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
5766

67+
$format = $input->getOption('format');
68+
if (!\in_array($format, $this->getAvailableFormatOptions(), true)) {
69+
throw new InvalidArgumentException('Invalid output format.');
70+
}
71+
5872
$transportNames = $this->transportNames;
5973
if ($input->getArgument('transport_names')) {
6074
$transportNames = $input->getArgument('transport_names');
@@ -64,7 +78,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6478
$uncountableTransports = [];
6579
foreach ($transportNames as $transportName) {
6680
if (!$this->transportLocator->has($transportName)) {
67-
$io->warning(\sprintf('The "%s" transport does not exist.', $transportName));
81+
if ($this->formatSupportsWarnings($format)) {
82+
$io->warning(\sprintf('The "%s" transport does not exist.', $transportName));
83+
}
6884

6985
continue;
7086
}
@@ -77,12 +93,48 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7793
$outputTable[] = [$transportName, $transport->getMessageCount()];
7894
}
7995

96+
match ($format) {
97+
'text' => $this->outputText($io, $outputTable, $uncountableTransports),
98+
'json' => $this->outputJson($io, $outputTable, $uncountableTransports),
99+
};
100+
101+
return 0;
102+
}
103+
104+
private function outputText(SymfonyStyle $io, array $outputTable, array $uncountableTransports): void
105+
{
80106
$io->table(['Transport', 'Count'], $outputTable);
81107

82108
if ($uncountableTransports) {
83109
$io->note(\sprintf('Unable to get message count for the following transports: "%s".', implode('", "', $uncountableTransports)));
84110
}
111+
}
85112

86-
return 0;
113+
private function outputJson(SymfonyStyle $io, array $outputTable, array $uncountableTransports): void
114+
{
115+
$output = ['transports' => []];
116+
foreach ($outputTable as [$transportName, $count]) {
117+
$output['transports'][$transportName] = ['count' => $count];
118+
}
119+
120+
if ($uncountableTransports) {
121+
$output['uncountable_transports'] = $uncountableTransports;
122+
}
123+
124+
$io->writeln(json_encode($output, \JSON_PRETTY_PRINT));
125+
}
126+
127+
private function formatSupportsWarnings(string $format): bool
128+
{
129+
return match ($format) {
130+
'text' => true,
131+
'json' => false,
132+
};
133+
}
134+
135+
/** @return string[] */
136+
private function getAvailableFormatOptions(): array
137+
{
138+
return ['text', 'json'];
87139
}
88140
}

src/Symfony/Component/Messenger/Tests/Command/StatsCommandTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,23 @@ public function testWithoutArgument()
6969
$this->assertStringContainsString('! [NOTE] Unable to get message count for the following transports: "simple".', $display);
7070
}
7171

72+
public function testWithoutArgumentJsonFormat()
73+
{
74+
$tester = new CommandTester($this->command);
75+
$tester->execute(['--format' => 'json']);
76+
$display = $tester->getDisplay();
77+
78+
$this->assertJsonStringEqualsJsonString('{
79+
"transports": {
80+
"message_countable": {"count": 6},
81+
"another_message_countable": {"count": 6}
82+
},
83+
"uncountable_transports": [
84+
"simple"
85+
]
86+
}', $display);
87+
}
88+
7289
public function testWithOneExistingMessageCountableTransport()
7390
{
7491
$tester = new CommandTester($this->command);
@@ -81,6 +98,19 @@ public function testWithOneExistingMessageCountableTransport()
8198
$this->assertStringNotContainsString(' ! [NOTE] Unable to get message count for the following transports: "simple".', $display);
8299
}
83100

101+
public function testWithOneExistingMessageCountableTransportJsonFormat()
102+
{
103+
$tester = new CommandTester($this->command);
104+
$tester->execute(['transport_names' => ['message_countable'], '--format' => 'json']);
105+
$display = $tester->getDisplay();
106+
107+
$this->assertJsonStringEqualsJsonString('{
108+
"transports": {
109+
"message_countable": {"count": 6}
110+
}
111+
}', $display);
112+
}
113+
84114
public function testWithMultipleExistingMessageCountableTransport()
85115
{
86116
$tester = new CommandTester($this->command);
@@ -93,6 +123,20 @@ public function testWithMultipleExistingMessageCountableTransport()
93123
$this->assertStringNotContainsString('! [NOTE] Unable to get message count for the following transports: "simple".', $display);
94124
}
95125

126+
public function testWithMultipleExistingMessageCountableTransportJsonFormat()
127+
{
128+
$tester = new CommandTester($this->command);
129+
$tester->execute(['transport_names' => ['message_countable', 'another_message_countable'], '--format' => 'json']);
130+
$display = $tester->getDisplay();
131+
132+
$this->assertJsonStringEqualsJsonString('{
133+
"transports": {
134+
"message_countable": {"count": 6},
135+
"another_message_countable": {"count": 6}
136+
}
137+
}', $display);
138+
}
139+
96140
public function testWithNotMessageCountableTransport()
97141
{
98142
$tester = new CommandTester($this->command);

0 commit comments

Comments
 (0)