@@ -123,7 +123,7 @@ protected function addMetricsOptions()
123123 /**
124124 * Returns the metrics URL and collection information for the selected environment.
125125 *
126- * @return array{' href' : string, ' collection' : string}|false
126+ * @return array{href: string, collection: string, max_range : string}|false
127127 * The link data or false on failure.
128128 */
129129 protected function getMetricsLink (Environment $ environment )
@@ -332,10 +332,11 @@ protected function fetchMetrics(InputInterface $input, TimeSpec $timeSpec, Envir
332332 * @see self::startTime, self::$endTime, self::$interval
333333 *
334334 * @param InputInterface $input
335+ * @param Environment $environment
335336 *
336337 * @return TimeSpec|false
337338 */
338- protected function validateTimeInput (InputInterface $ input )
339+ protected function validateTimeInput (InputInterface $ input, Environment $ environment )
339340 {
340341 $ interval = null ;
341342 if ($ intervalStr = $ input ->getOption ('interval ' )) {
@@ -361,13 +362,24 @@ protected function validateTimeInput(InputInterface $input)
361362 $ endTime = time ();
362363 }
363364 if ($ rangeStr = $ input ->getOption ('range ' )) {
364- $ rangeSeconds = (new Duration ())->toSeconds ($ rangeStr );
365+ $ rangeDuration = $ this ->parseDuration ($ rangeStr );
366+ if (!$ rangeDuration ) {
367+ $ this ->stdErr ->writeln ('Invalid --range: <error> ' . $ rangeStr . '</error> ' );
368+ return false ;
369+ }
370+ $ rangeSeconds = $ rangeDuration ->toSeconds ();
365371 if (empty ($ rangeSeconds )) {
366372 $ this ->stdErr ->writeln ('Invalid --range: <error> ' . $ rangeStr . '</error> ' );
367373 return false ;
368374 } elseif ($ rangeSeconds < self ::MIN_RANGE ) {
369375 $ this ->stdErr ->writeln (\sprintf ('The --range <error>%s</error> is too short: it must be at least %d seconds (%s). ' , $ rangeStr , self ::MIN_RANGE , (new Duration ())->humanize (self ::MIN_RANGE )));
370376 return false ;
377+ } elseif (($ link = $ this ->getMetricsLink ($ environment )) && isset ($ link ['max_range ' ])) {
378+ $ maxRange = $ this ->parseDuration ($ link ['max_range ' ]);
379+ if ($ rangeSeconds > $ maxRange ->toSeconds ()) {
380+ $ this ->stdErr ->writeln (\sprintf ('The --range <error>%s</error> is too long: the maximum is %s. ' , $ rangeStr , $ link ['max_range ' ]));
381+ return false ;
382+ }
371383 }
372384 $ rangeSeconds = \intval ($ rangeSeconds );
373385 } else {
@@ -404,10 +416,9 @@ protected function validateTimeInput(InputInterface $input)
404416 */
405417 private function defaultInterval ($ range )
406418 {
407- $ divisor = 5 ; // Number of points per time range.
408- // Number of seconds to round to:
409- $ granularity = 10 ;
410- foreach ([3600 *24 , 3600 *6 , 3600 *3 , 3600 , 600 , 300 , 60 , 30 ] as $ level ) {
419+ $ divisor = 6 ; // Minimum number of points per time range.
420+ $ granularity = 10 ; // Number of seconds to round to.
421+ 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 ) {
411422 if ($ range >= $ level * $ divisor ) {
412423 $ granularity = $ level ;
413424 break ;
@@ -421,6 +432,22 @@ private function defaultInterval($range)
421432 return (int ) $ interval ;
422433 }
423434
435+ /**
436+ * @param string $duration
437+ * @return Duration|false
438+ */
439+ private function parseDuration ($ duration )
440+ {
441+ if (substr ($ duration , -1 ) === 'y ' ) {
442+ $ num = rtrim ($ duration , 'y ' );
443+ if (!is_numeric ($ num )) {
444+ return false ;
445+ }
446+ return new Duration (intval ($ num ) * 365.25 * 86400 );
447+ }
448+ return (new Duration ())->parse ($ duration );
449+ }
450+
424451 /**
425452 * Returns the deployment type of an environment (needed for differing queries).
426453 *
0 commit comments