@@ -100,7 +100,7 @@ protected function addMetricsOptions()
100100 $ duration = new Duration ();
101101 $ this ->addOption ('range ' , 'r ' , InputOption::VALUE_REQUIRED ,
102102 'The time range. Metrics will be loaded for this duration until the end time (--to). '
103- . "\n" . 'You can specify units: hours (h ), minutes (m ), or seconds (s ). '
103+ . "\n" . 'You can specify units: s (seconds ), m ( minutes), h (hours ), d (days), w (weeks), or y (years ). '
104104 . "\n" . \sprintf (
105105 'Minimum <comment>%s</comment>, maximum <comment>8h</comment> or more (depending on the project), default <comment>%s</comment>. ' ,
106106 $ duration ->humanize (self ::MIN_RANGE ),
@@ -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,26 @@ private function defaultInterval($range)
421432 return (int ) $ interval ;
422433 }
423434
435+ /**
436+ * Parses a duration.
437+ *
438+ * Supports 'y' and 'w' in addition to the Duration class's suffixes of
439+ * 'h', 'm', and 'd'.
440+ *
441+ * @param string $duration
442+ * @return Duration|false
443+ */
444+ private function parseDuration ($ duration )
445+ {
446+ if (preg_match ('/^([0-9.]+)\s*y$/i ' , $ duration , $ matches ) === 1 ) {
447+ return new Duration (floatval ($ matches [1 ]) * 365.25 * 86400 );
448+ }
449+ if (preg_match ('/^([0-9.]+)\s*w$/i ' , $ duration , $ matches ) === 1 ) {
450+ return new Duration (floatval ($ matches [1 ]) * 7 * 86400 );
451+ }
452+ return (new Duration ())->parse ($ duration );
453+ }
454+
424455 /**
425456 * Returns the deployment type of an environment (needed for differing queries).
426457 *
0 commit comments