| 675 | } |
| 676 | |
| 677 | func validateQueryTimeRange(ctx context.Context, userID string, startMs, endMs int64, limits *validation.Overrides, maxQueryIntoFuture time.Duration) (int64, int64, error) { |
| 678 | now := model.Now() |
| 679 | startTime := model.Time(startMs) |
| 680 | endTime := model.Time(endMs) |
| 681 | |
| 682 | // Clamp time range based on max query into future. |
| 683 | if maxQueryIntoFuture > 0 && endTime.After(now.Add(maxQueryIntoFuture)) { |
| 684 | origEndTime := endTime |
| 685 | endTime = now.Add(maxQueryIntoFuture) |
| 686 | |
| 687 | // Make sure to log it in traces to ease debugging. |
| 688 | level.Debug(spanlogger.FromContext(ctx)).Log( |
| 689 | "msg", "the end time of the query has been manipulated because of the 'max query into future' setting", |
| 690 | "original", util.FormatTimeModel(origEndTime), |
| 691 | "updated", util.FormatTimeModel(endTime)) |
| 692 | |
| 693 | if endTime.Before(startTime) { |
| 694 | return 0, 0, errEmptyTimeRange |
| 695 | } |
| 696 | } |
| 697 | |
| 698 | // Clamp the time range based on the max query lookback. |
| 699 | if maxQueryLookback := limits.MaxQueryLookback(userID); maxQueryLookback > 0 && startTime.Before(now.Add(-maxQueryLookback)) { |
| 700 | origStartTime := startTime |
| 701 | startTime = now.Add(-maxQueryLookback) |
| 702 | |
| 703 | // Make sure to log it in traces to ease debugging. |
| 704 | level.Debug(spanlogger.FromContext(ctx)).Log( |
| 705 | "msg", "the start time of the query has been manipulated because of the 'max query lookback' setting", |
| 706 | "original", util.FormatTimeModel(origStartTime), |
| 707 | "updated", util.FormatTimeModel(startTime)) |
| 708 | |
| 709 | if endTime.Before(startTime) { |
| 710 | return 0, 0, errEmptyTimeRange |
| 711 | } |
| 712 | } |
| 713 | |
| 714 | // start time should be at least non-negative to avoid int64 overflow. |
| 715 | if startTime < 0 { |
| 716 | startTime = 0 |
| 717 | } |
| 718 | |
| 719 | return int64(startTime), int64(endTime), nil |
| 720 | } |