|
4 | 4 |
|
5 | 5 | namespace Platformsh\Cli\Command\Metrics; |
6 | 6 |
|
| 7 | +use Platformsh\Cli\Model\Metrics\Aggregation; |
| 8 | +use Platformsh\Cli\Model\Metrics\Field; |
| 9 | +use Platformsh\Cli\Model\Metrics\Format; |
| 10 | +use Platformsh\Cli\Model\Metrics\MetricKind; |
| 11 | +use Platformsh\Cli\Model\Metrics\SourceField; |
| 12 | +use Platformsh\Cli\Model\Metrics\SourceFieldPercentage; |
7 | 13 | use Platformsh\Cli\Selector\SelectorConfig; |
8 | 14 | use Platformsh\Cli\Selector\Selector; |
9 | 15 | use Khill\Duration\Duration; |
10 | | -use Platformsh\Cli\Model\Metrics\Field; |
11 | 16 | use Platformsh\Cli\Service\PropertyFormatter; |
12 | 17 | use Platformsh\Cli\Service\Table; |
13 | 18 | use Symfony\Component\Console\Attribute\AsCommand; |
|
19 | 24 | class AllMetricsCommand extends MetricsCommandBase |
20 | 25 | { |
21 | 26 | /** @var array<string, string> */ |
22 | | - private array $tableHeader = [ |
| 27 | + private const TABLE_HEADER = [ |
23 | 28 | 'timestamp' => 'Timestamp', |
24 | 29 | 'service' => 'Service', |
25 | 30 | 'type' => 'Type', |
@@ -50,91 +55,167 @@ class AllMetricsCommand extends MetricsCommandBase |
50 | 55 | ]; |
51 | 56 |
|
52 | 57 | /** @var string[] */ |
53 | | - private array $defaultColumns = ['timestamp', 'service', 'cpu_percent', 'mem_percent', 'disk_percent', 'tmp_disk_percent']; |
54 | | - public function __construct(private readonly PropertyFormatter $propertyFormatter, private readonly Selector $selector, private readonly Table $table) |
55 | | - { |
56 | | - parent::__construct(); |
| 58 | + private array $defaultColumns = [ |
| 59 | + 'timestamp', |
| 60 | + 'service', |
| 61 | + |
| 62 | + 'cpu_percent', |
| 63 | + 'mem_percent', |
| 64 | + 'disk_percent', |
| 65 | + 'inodes_percent', |
| 66 | + |
| 67 | + 'tmp_disk_percent', |
| 68 | + 'tmp_inodes_percent', |
| 69 | + ]; |
| 70 | + |
| 71 | + public function __construct( |
| 72 | + private readonly PropertyFormatter $propertyFormatter, |
| 73 | + Selector $selector, |
| 74 | + Table $table |
| 75 | + ) { |
| 76 | + parent::__construct($selector, $table); |
57 | 77 | } |
58 | 78 |
|
59 | 79 | protected function configure(): void |
60 | 80 | { |
61 | 81 | $this->addOption('bytes', 'B', InputOption::VALUE_NONE, 'Show sizes in bytes'); |
62 | 82 | $this->addExample('Show metrics for the last ' . (new Duration())->humanize(self::DEFAULT_RANGE)); |
63 | | - $this->addExample('Show metrics in five-minute intervals over the last hour', '-i 5m -r 1h'); |
| 83 | + $this->addExample('Show metrics over the last hour', ' -r 1h'); |
64 | 84 | $this->addExample('Show metrics for all SQL services', '--type mariadb,%sql'); |
65 | 85 | $this->addMetricsOptions(); |
66 | 86 | $this->selector->addProjectOption($this->getDefinition()); |
67 | 87 | $this->selector->addEnvironmentOption($this->getDefinition()); |
68 | 88 | $this->addCompleter($this->selector); |
69 | | - Table::configureInput($this->getDefinition(), $this->tableHeader, $this->defaultColumns); |
| 89 | + Table::configureInput($this->getDefinition(), self::TABLE_HEADER, $this->defaultColumns); |
70 | 90 | PropertyFormatter::configureInput($this->getDefinition()); |
71 | 91 | } |
72 | 92 |
|
73 | | - /** |
74 | | - * {@inheritdoc} |
75 | | - */ |
76 | | - protected function execute(InputInterface $input, OutputInterface $output): int |
| 93 | + protected function getChooseEnvFilter(): ?callable |
77 | 94 | { |
78 | | - $timeSpec = $this->validateTimeInput($input); |
79 | | - if ($timeSpec === false) { |
80 | | - return 1; |
81 | | - } |
82 | | - |
83 | | - $selection = $this->selector->getSelection($input, new SelectorConfig(selectDefaultEnv: true, chooseEnvFilter: SelectorConfig::filterEnvsMaybeActive())); |
84 | | - |
85 | | - if (!$this->table->formatIsMachineReadable()) { |
86 | | - $this->selector->ensurePrintedSelection($selection); |
87 | | - } |
| 95 | + return SelectorConfig::filterEnvsMaybeActive(); |
| 96 | + } |
88 | 97 |
|
89 | | - // Only request the metrics fields that will be displayed. |
90 | | - // |
91 | | - // The fields are the selected column names (according to the $table |
92 | | - // service), filtered to only those that contain an underscore. |
93 | | - $fieldNames = array_filter($this->table->columnsToDisplay($this->tableHeader, $this->defaultColumns), fn($c): bool => str_contains((string) $c, '_')); |
94 | | - $values = $this->fetchMetrics($input, $timeSpec, $selection->getEnvironment(), $fieldNames); |
95 | | - if ($values === false) { |
96 | | - return 1; |
97 | | - } |
| 98 | + protected function execute(InputInterface $input, OutputInterface $output): int |
| 99 | + { |
| 100 | + [$values, $environment] = $this->processQuery($input, [ |
| 101 | + MetricKind::API_TYPE_CPU, |
| 102 | + MetricKind::API_TYPE_DISK, |
| 103 | + MetricKind::API_TYPE_MEMORY, |
| 104 | + MetricKind::API_TYPE_INODES, |
| 105 | + ], [MetricKind::API_AGG_AVG]); |
98 | 106 |
|
99 | 107 | $bytes = $input->getOption('bytes'); |
100 | 108 |
|
101 | 109 | $rows = $this->buildRows($values, [ |
102 | | - 'cpu_used' => new Field('cpu_used', Field::FORMAT_ROUNDED_2DP), |
103 | | - 'cpu_limit' => new Field('cpu_limit', Field::FORMAT_ROUNDED_2DP), |
104 | | - 'cpu_percent' => new Field('cpu_percent', Field::FORMAT_PERCENT), |
105 | | - |
106 | | - 'mem_used' => new Field('mem_used', $bytes ? Field::FORMAT_ROUNDED : Field::FORMAT_MEMORY), |
107 | | - 'mem_limit' => new Field('mem_limit', $bytes ? Field::FORMAT_ROUNDED : Field::FORMAT_MEMORY), |
108 | | - 'mem_percent' => new Field('mem_percent', Field::FORMAT_PERCENT), |
109 | | - |
110 | | - 'disk_used' => new Field('disk_used', $bytes ? Field::FORMAT_ROUNDED : Field::FORMAT_DISK), |
111 | | - 'disk_limit' => new Field('disk_limit', $bytes ? Field::FORMAT_ROUNDED : Field::FORMAT_DISK), |
112 | | - 'disk_percent' => new Field('disk_percent', Field::FORMAT_PERCENT), |
113 | | - |
114 | | - 'tmp_disk_used' => new Field('tmp_disk_used', $bytes ? Field::FORMAT_ROUNDED : Field::FORMAT_DISK), |
115 | | - 'tmp_disk_limit' => new Field('tmp_disk_limit', $bytes ? Field::FORMAT_ROUNDED : Field::FORMAT_DISK), |
116 | | - 'tmp_disk_percent' => new Field('tmp_disk_percent', Field::FORMAT_PERCENT), |
117 | | - |
118 | | - 'inodes_used' => new Field('inodes_used', Field::FORMAT_ROUNDED), |
119 | | - 'inodes_limit' => new Field('inodes_used', Field::FORMAT_ROUNDED), |
120 | | - 'inodes_percent' => new Field('inodes_percent', Field::FORMAT_PERCENT), |
121 | | - |
122 | | - 'tmp_inodes_used' => new Field('tmp_inodes_used', Field::FORMAT_ROUNDED), |
123 | | - 'tmp_inodes_limit' => new Field('tmp_inodes_used', Field::FORMAT_ROUNDED), |
124 | | - 'tmp_inodes_percent' => new Field('tmp_inodes_percent', Field::FORMAT_PERCENT), |
125 | | - ], $selection->getEnvironment()); |
| 110 | + 'cpu_used' => new Field( |
| 111 | + Format::Rounded2p, |
| 112 | + new SourceField(MetricKind::CpuUsed, Aggregation::Avg), |
| 113 | + ), |
| 114 | + 'cpu_limit' => new Field( |
| 115 | + Format::Rounded2p, |
| 116 | + new SourceField(MetricKind::CpuLimit, Aggregation::Max), |
| 117 | + ), |
| 118 | + 'cpu_percent' => new Field( |
| 119 | + Format::Percent, |
| 120 | + new SourceFieldPercentage( |
| 121 | + new SourceField(MetricKind::CpuUsed, Aggregation::Avg), |
| 122 | + new SourceField(MetricKind::CpuLimit, Aggregation::Max) |
| 123 | + ), |
| 124 | + ), |
| 125 | + |
| 126 | + 'mem_used' => new Field( |
| 127 | + $bytes ? Format::Rounded : Format::Memory, |
| 128 | + new SourceField(MetricKind::MemoryUsed, Aggregation::Avg), |
| 129 | + ), |
| 130 | + 'mem_limit' => new Field( |
| 131 | + $bytes ? Format::Rounded : Format::Memory, |
| 132 | + new SourceField(MetricKind::MemoryLimit, Aggregation::Max), |
| 133 | + ), |
| 134 | + 'mem_percent' => new Field( |
| 135 | + Format::Percent, |
| 136 | + new SourceFieldPercentage( |
| 137 | + new SourceField(MetricKind::MemoryUsed, Aggregation::Avg), |
| 138 | + new SourceField(MetricKind::MemoryLimit, Aggregation::Max) |
| 139 | + ), |
| 140 | + false, |
| 141 | + ), |
| 142 | + |
| 143 | + 'disk_used' => new Field( |
| 144 | + $bytes ? Format::Rounded : Format::Disk, |
| 145 | + new SourceField(MetricKind::DiskUsed, Aggregation::Avg, '/mnt'), |
| 146 | + ), |
| 147 | + 'disk_limit' => new Field( |
| 148 | + $bytes ? Format::Rounded : Format::Disk, |
| 149 | + new SourceField(MetricKind::DiskLimit, Aggregation::Max, '/mnt'), |
| 150 | + ), |
| 151 | + 'disk_percent' => new Field( |
| 152 | + Format::Percent, |
| 153 | + new SourceFieldPercentage( |
| 154 | + new SourceField(MetricKind::DiskUsed, Aggregation::Avg, '/mnt'), |
| 155 | + new SourceField(MetricKind::DiskLimit, Aggregation::Max, '/mnt') |
| 156 | + ), |
| 157 | + ), |
| 158 | + |
| 159 | + 'tmp_disk_used' => new Field( |
| 160 | + $bytes ? Format::Rounded : Format::Disk, |
| 161 | + new SourceField(MetricKind::DiskUsed, Aggregation::Avg, '/tmp'), |
| 162 | + ), |
| 163 | + 'tmp_disk_limit' => new Field( |
| 164 | + $bytes ? Format::Rounded : Format::Disk, |
| 165 | + new SourceField(MetricKind::DiskLimit, Aggregation::Max, '/tmp'), |
| 166 | + ), |
| 167 | + 'tmp_disk_percent' => new Field( |
| 168 | + Format::Percent, |
| 169 | + new SourceFieldPercentage( |
| 170 | + new SourceField(MetricKind::DiskUsed, Aggregation::Avg, '/tmp'), |
| 171 | + new SourceField(MetricKind::DiskLimit, Aggregation::Max, '/tmp') |
| 172 | + ), |
| 173 | + ), |
| 174 | + |
| 175 | + 'inodes_used' => new Field( |
| 176 | + Format::Rounded, |
| 177 | + new SourceField(MetricKind::InodesUsed, Aggregation::Avg, '/mnt'), |
| 178 | + ), |
| 179 | + 'inodes_limit' => new Field( |
| 180 | + Format::Rounded, |
| 181 | + new SourceField(MetricKind::InodesLimit, Aggregation::Max, '/mnt'), |
| 182 | + ), |
| 183 | + 'inodes_percent' => new Field( |
| 184 | + Format::Percent, |
| 185 | + new SourceFieldPercentage( |
| 186 | + new SourceField(MetricKind::InodesUsed, Aggregation::Avg, '/mnt'), |
| 187 | + new SourceField(MetricKind::InodesLimit, Aggregation::Max, '/mnt') |
| 188 | + ), |
| 189 | + ), |
| 190 | + |
| 191 | + 'tmp_inodes_used' => new Field( |
| 192 | + Format::Rounded, |
| 193 | + new SourceField(MetricKind::InodesUsed, Aggregation::Avg, '/tmp'), |
| 194 | + ), |
| 195 | + 'tmp_inodes_limit' => new Field( |
| 196 | + Format::Rounded, |
| 197 | + new SourceField(MetricKind::InodesLimit, Aggregation::Max, '/tmp'), |
| 198 | + ), |
| 199 | + 'tmp_inodes_percent' => new Field( |
| 200 | + Format::Percent, |
| 201 | + new SourceFieldPercentage( |
| 202 | + new SourceField(MetricKind::InodesUsed, Aggregation::Avg, '/tmp'), |
| 203 | + new SourceField(MetricKind::InodesLimit, Aggregation::Max, '/tmp') |
| 204 | + ), |
| 205 | + ), |
| 206 | + ], $environment); |
126 | 207 |
|
127 | 208 | if (!$this->table->formatIsMachineReadable()) { |
128 | 209 | $formatter = $this->propertyFormatter; |
129 | 210 | $this->stdErr->writeln(\sprintf( |
130 | 211 | 'Metrics at <info>%s</info> intervals from <info>%s</info> to <info>%s</info>:', |
131 | | - (new Duration())->humanize($timeSpec->getInterval()), |
132 | | - $formatter->formatDate($timeSpec->getStartTime()), |
133 | | - $formatter->formatDate($timeSpec->getEndTime()), |
| 212 | + (new Duration())->humanize($values['_grain']), |
| 213 | + $formatter->formatDate($values['_from']), |
| 214 | + $formatter->formatDate($values['_to']), |
134 | 215 | )); |
135 | 216 | } |
136 | 217 |
|
137 | | - $this->table->render($rows, $this->tableHeader, $this->defaultColumns); |
| 218 | + $this->table->render($rows, self::TABLE_HEADER, $this->defaultColumns); |
138 | 219 |
|
139 | 220 | if (!$this->table->formatIsMachineReadable()) { |
140 | 221 | $this->explainHighMemoryServices(); |
|
0 commit comments