diff --git a/src/Command/Metrics/AllMetricsCommand.php b/src/Command/Metrics/AllMetricsCommand.php
index e7573c64aa..4512fa3adc 100644
--- a/src/Command/Metrics/AllMetricsCommand.php
+++ b/src/Command/Metrics/AllMetricsCommand.php
@@ -67,14 +67,14 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $timeSpec = $this->validateTimeInput($input);
+ $this->chooseEnvFilter = $this->filterEnvsByState(['active']);
+ $this->validateInput($input, false, true);
+
+ $timeSpec = $this->validateTimeInput($input, $this->getSelectedEnvironment());
if ($timeSpec === false) {
return 1;
}
- $this->chooseEnvFilter = $this->filterEnvsByState(['active']);
- $this->validateInput($input, false, true);
-
/** @var \Platformsh\Cli\Service\Table $table */
$table = $this->getService('table');
diff --git a/src/Command/Metrics/CpuCommand.php b/src/Command/Metrics/CpuCommand.php
index 9743da7218..251a2bad37 100644
--- a/src/Command/Metrics/CpuCommand.php
+++ b/src/Command/Metrics/CpuCommand.php
@@ -41,13 +41,14 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $timeSpec = $this->validateTimeInput($input);
+ $this->chooseEnvFilter = $this->filterEnvsByState(['active']);
+ $this->validateInput($input, false, true);
+
+ $timeSpec = $this->validateTimeInput($input, $this->getSelectedEnvironment());
if ($timeSpec === false) {
return 1;
}
- $this->validateInput($input, false, true);
-
/** @var \Platformsh\Cli\Service\Table $table */
$table = $this->getService('table');
diff --git a/src/Command/Metrics/CurlCommand.php b/src/Command/Metrics/CurlCommand.php
index c4a671b375..41ce1ff7a9 100644
--- a/src/Command/Metrics/CurlCommand.php
+++ b/src/Command/Metrics/CurlCommand.php
@@ -22,6 +22,7 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output)
{
+ $this->chooseEnvFilter = $this->filterEnvsByState(['active']);
$this->validateInput($input, false, true);
// Initialize the API service so that it gets CommandBase's event listeners
diff --git a/src/Command/Metrics/DiskUsageCommand.php b/src/Command/Metrics/DiskUsageCommand.php
index b206e9fc04..2f1052917b 100644
--- a/src/Command/Metrics/DiskUsageCommand.php
+++ b/src/Command/Metrics/DiskUsageCommand.php
@@ -53,7 +53,10 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $timeSpec = $this->validateTimeInput($input);
+ $this->chooseEnvFilter = $this->filterEnvsByState(['active']);
+ $this->validateInput($input, false, true);
+
+ $timeSpec = $this->validateTimeInput($input, $this->getSelectedEnvironment());
if ($timeSpec === false) {
return 1;
}
@@ -66,8 +69,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
$table = $this->getService('table');
$table->removeDeprecatedColumns(['interval'], '', $input, $output);
- $this->validateInput($input, false, true);
-
if (!$table->formatIsMachineReadable()) {
$this->displayEnvironmentHeader();
}
diff --git a/src/Command/Metrics/MemCommand.php b/src/Command/Metrics/MemCommand.php
index c109b44b33..8bee6f4ebb 100644
--- a/src/Command/Metrics/MemCommand.php
+++ b/src/Command/Metrics/MemCommand.php
@@ -43,13 +43,14 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $timeSpec = $this->validateTimeInput($input);
+ $this->chooseEnvFilter = $this->filterEnvsByState(['active']);
+ $this->validateInput($input, false, true);
+
+ $timeSpec = $this->validateTimeInput($input, $this->getSelectedEnvironment());
if ($timeSpec === false) {
return 1;
}
- $this->validateInput($input, false, true);
-
/** @var \Platformsh\Cli\Service\Table $table */
$table = $this->getService('table');
diff --git a/src/Command/Metrics/MetricsCommandBase.php b/src/Command/Metrics/MetricsCommandBase.php
index a982f87691..c1fd26359d 100644
--- a/src/Command/Metrics/MetricsCommandBase.php
+++ b/src/Command/Metrics/MetricsCommandBase.php
@@ -100,7 +100,7 @@ protected function addMetricsOptions()
$duration = new Duration();
$this->addOption('range', 'r', InputOption::VALUE_REQUIRED,
'The time range. Metrics will be loaded for this duration until the end time (--to).'
- . "\n" . 'You can specify units: hours (h), minutes (m), or seconds (s).'
+ . "\n" . 'You can specify units: s (seconds), m (minutes), h (hours), d (days), w (weeks), or y (years).'
. "\n" . \sprintf(
'Minimum %s, maximum 8h or more (depending on the project), default %s.',
$duration->humanize(self::MIN_RANGE),
@@ -123,7 +123,7 @@ protected function addMetricsOptions()
/**
* Returns the metrics URL and collection information for the selected environment.
*
- * @return array{'href': string, 'collection': string}|false
+ * @return array{href: string, collection: string, max_range: string}|false
* The link data or false on failure.
*/
protected function getMetricsLink(Environment $environment)
@@ -332,10 +332,11 @@ protected function fetchMetrics(InputInterface $input, TimeSpec $timeSpec, Envir
* @see self::startTime, self::$endTime, self::$interval
*
* @param InputInterface $input
+ * @param Environment $environment
*
* @return TimeSpec|false
*/
- protected function validateTimeInput(InputInterface $input)
+ protected function validateTimeInput(InputInterface $input, Environment $environment)
{
$interval = null;
if ($intervalStr = $input->getOption('interval')) {
@@ -361,13 +362,24 @@ protected function validateTimeInput(InputInterface $input)
$endTime = time();
}
if ($rangeStr = $input->getOption('range')) {
- $rangeSeconds = (new Duration())->toSeconds($rangeStr);
+ $rangeDuration = $this->parseDuration($rangeStr);
+ if (!$rangeDuration) {
+ $this->stdErr->writeln('Invalid --range: ' . $rangeStr . '');
+ return false;
+ }
+ $rangeSeconds = $rangeDuration->toSeconds();
if (empty($rangeSeconds)) {
$this->stdErr->writeln('Invalid --range: ' . $rangeStr . '');
return false;
} elseif ($rangeSeconds < self::MIN_RANGE) {
$this->stdErr->writeln(\sprintf('The --range %s is too short: it must be at least %d seconds (%s).', $rangeStr, self::MIN_RANGE, (new Duration())->humanize(self::MIN_RANGE)));
return false;
+ } elseif (($link = $this->getMetricsLink($environment)) && isset($link['max_range'])) {
+ $maxRange = $this->parseDuration($link['max_range']);
+ if ($rangeSeconds > $maxRange->toSeconds()) {
+ $this->stdErr->writeln(\sprintf('The --range %s is too long: the maximum is %s.', $rangeStr, $link['max_range']));
+ return false;
+ }
}
$rangeSeconds = \intval($rangeSeconds);
} else {
@@ -404,10 +416,9 @@ protected function validateTimeInput(InputInterface $input)
*/
private function defaultInterval($range)
{
- $divisor = 5; // Number of points per time range.
- // Number of seconds to round to:
- $granularity = 10;
- foreach ([3600*24, 3600*6, 3600*3, 3600, 600, 300, 60, 30] as $level) {
+ $divisor = 6; // Minimum number of points per time range.
+ $granularity = 10; // Number of seconds to round to.
+ foreach ([3600*24*365, 3600*24*90, 3600*24*30, 3600*24*7, 3600*24, 3600*6, 3600*3, 3600, 600, 300, 60, 30] as $level) {
if ($range >= $level * $divisor) {
$granularity = $level;
break;
@@ -421,6 +432,26 @@ private function defaultInterval($range)
return (int) $interval;
}
+ /**
+ * Parses a duration.
+ *
+ * Supports 'y' and 'w' in addition to the Duration class's suffixes of
+ * 'h', 'm', and 'd'.
+ *
+ * @param string $duration
+ * @return Duration|false
+ */
+ private function parseDuration($duration)
+ {
+ if (preg_match('/^([0-9.]+)\s*y$/i', $duration, $matches) === 1) {
+ return new Duration(floatval($matches[1]) * 365.25 * 86400);
+ }
+ if (preg_match('/^([0-9.]+)\s*w$/i', $duration, $matches) === 1) {
+ return new Duration(floatval($matches[1]) * 7 * 86400);
+ }
+ return (new Duration())->parse($duration);
+ }
+
/**
* Returns the deployment type of an environment (needed for differing queries).
*