mirror of
https://github.com/grafana/grafana.git
synced 2024-11-26 19:00:54 -06:00
1083bef030
* Add select component for choosing step option * Add onStepChange * Add functionality for max step * Rename minInterval to stepInterval to describe min, max and exact step interval * Change select option from standard to exact * Add new type StepType for better type safety * Add tests for adjustInterval * Add functionality and tests for exact step option * Prometheus: Spell out min and max in select component * Prometheus: Change width of step select component and add placeholder * Prometheus: Adjust for the factor in exact step * Prometheus: Update tooltip of step lable to include max and exact options and add padding to select component to give it some breathing room from other components * Update snapshot for step tooltip * Prometheus: make tooltip more informative * Prometheus: add tooltip to interval input element * Prometheus: extract default step option * Prometheus: update snapshot for PromQueryEditor * Prometheus: change step labels to uppercase * Prometheus: define a default step option * Prometheus: use default step option in both ui component and logic * Prometheus: update snapshot for PromQueryEditor * Prometheus: refactor datasource.ts for better readability * Prometheus: change tool tip for step * Prometheus: update snapshots * Prometheus: add correct styling * Prometheus: update snapshots * Prometheus change variable name to something less superfluous * Prometheus: refactor * Prometheus: add new test for adjustInterval * Docs: Update docummentation on the step parameter for prometheus * Prometheus: make step input field smaller and change placeholder text to 15s * Prometheus: update snapshots * Prometheus: Make stepMode uniform in all places in the code * Adjust step based on stepMode * Adjust comment * Check if we have queryInterval * Refactor, add safe interval * Fix merge resolutions * Fix tests and add tests * Update snapshot * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/datasources/prometheus.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Implement calculation with intervalMode in calculator.go * Update tests, add calculate safe interval method * Replace panic with error * Update pkg/tsdb/interval/interval_test.go Co-authored-by: idafurjes <36131195+idafurjes@users.noreply.github.com> * Update pkg/tsdb/calculator_test.go Co-authored-by: idafurjes <36131195+idafurjes@users.noreply.github.com> * Impotrt require * Remove lint errors Co-authored-by: Olof Bourghardt <ob655088@gmail.com> Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> Co-authored-by: idafurjes <36131195+idafurjes@users.noreply.github.com>
254 lines
6.9 KiB
Go
254 lines
6.9 KiB
Go
package tsdb
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
"github.com/grafana/grafana/pkg/components/gtime"
|
|
"github.com/grafana/grafana/pkg/tsdb/interval"
|
|
)
|
|
|
|
var (
|
|
defaultRes int64 = 1500
|
|
defaultMinInterval = time.Millisecond * 1
|
|
year = time.Hour * 24 * 365
|
|
day = time.Hour * 24
|
|
)
|
|
|
|
type IntervalMode string
|
|
|
|
const (
|
|
Min IntervalMode = "min"
|
|
Max IntervalMode = "max"
|
|
Exact IntervalMode = "exact"
|
|
)
|
|
|
|
type Interval struct {
|
|
Text string
|
|
Value time.Duration
|
|
}
|
|
|
|
type intervalCalculator struct {
|
|
minInterval time.Duration
|
|
}
|
|
|
|
type Calculator interface {
|
|
Calculate(timerange backend.TimeRange, minInterval time.Duration, intervalMode IntervalMode) (Interval, error)
|
|
CalculateSafeInterval(timerange backend.TimeRange, resolution int64) Interval
|
|
}
|
|
|
|
type CalculatorOptions struct {
|
|
MinInterval time.Duration
|
|
}
|
|
|
|
func NewCalculator(opts ...CalculatorOptions) *intervalCalculator {
|
|
calc := &intervalCalculator{}
|
|
|
|
for _, o := range opts {
|
|
if o.MinInterval == 0 {
|
|
calc.minInterval = defaultMinInterval
|
|
} else {
|
|
calc.minInterval = o.MinInterval
|
|
}
|
|
}
|
|
|
|
return calc
|
|
}
|
|
|
|
func (i *Interval) Milliseconds() int64 {
|
|
return i.Value.Nanoseconds() / int64(time.Millisecond)
|
|
}
|
|
|
|
func (ic *intervalCalculator) Calculate(timerange backend.TimeRange, intrvl time.Duration, intervalMode IntervalMode) (Interval, error) {
|
|
to := timerange.To.UnixNano()
|
|
from := timerange.From.UnixNano()
|
|
calculatedIntrvl := time.Duration((to - from) / defaultRes)
|
|
|
|
switch intervalMode {
|
|
case Min:
|
|
if calculatedIntrvl < intrvl {
|
|
return Interval{Text: interval.FormatDuration(intrvl), Value: intrvl}, nil
|
|
}
|
|
case Max:
|
|
if calculatedIntrvl > intrvl {
|
|
return Interval{Text: interval.FormatDuration(intrvl), Value: intrvl}, nil
|
|
}
|
|
case Exact:
|
|
return Interval{Text: interval.FormatDuration(intrvl), Value: intrvl}, nil
|
|
|
|
default:
|
|
return Interval{}, fmt.Errorf("unrecognized intervalMode: %v", intervalMode)
|
|
}
|
|
|
|
rounded := roundInterval(calculatedIntrvl)
|
|
return Interval{Text: interval.FormatDuration(rounded), Value: rounded}, nil
|
|
}
|
|
|
|
func (ic *intervalCalculator) CalculateSafeInterval(timerange backend.TimeRange, safeRes int64) Interval {
|
|
to := timerange.To.UnixNano()
|
|
from := timerange.From.UnixNano()
|
|
safeInterval := time.Duration((to - from) / safeRes)
|
|
|
|
rounded := roundInterval(safeInterval)
|
|
return Interval{Text: interval.FormatDuration(rounded), Value: rounded}
|
|
}
|
|
|
|
// GetIntervalFrom returns the minimum interval.
|
|
// dsInterval is the string representation of data source min interval, if configured.
|
|
// queryInterval is the string representation of query interval (min interval), e.g. "10ms" or "10s".
|
|
// queryIntervalMS is a pre-calculated numeric representation of the query interval in milliseconds.
|
|
func GetIntervalFrom(dsInterval, queryInterval string, queryIntervalMS int64, defaultInterval time.Duration) (time.Duration, error) {
|
|
if queryInterval == "" {
|
|
if queryIntervalMS != 0 {
|
|
return time.Duration(queryIntervalMS) * time.Millisecond, nil
|
|
}
|
|
}
|
|
interval := queryInterval
|
|
if queryInterval == "" && dsInterval != "" {
|
|
interval = dsInterval
|
|
}
|
|
if interval == "" {
|
|
return defaultInterval, nil
|
|
}
|
|
interval = strings.Replace(strings.Replace(interval, "<", "", 1), ">", "", 1)
|
|
isPureNum, err := regexp.MatchString(`^\d+$`, interval)
|
|
if err != nil {
|
|
return time.Duration(0), err
|
|
}
|
|
if isPureNum {
|
|
interval += "s"
|
|
}
|
|
parsedInterval, err := gtime.ParseDuration(interval)
|
|
if err != nil {
|
|
return time.Duration(0), err
|
|
}
|
|
return parsedInterval, nil
|
|
}
|
|
|
|
// FormatDuration converts a duration into the kbn format e.g. 1m 2h or 3d
|
|
func FormatDuration(inter time.Duration) string {
|
|
if inter >= year {
|
|
return fmt.Sprintf("%dy", inter/year)
|
|
}
|
|
|
|
if inter >= day {
|
|
return fmt.Sprintf("%dd", inter/day)
|
|
}
|
|
|
|
if inter >= time.Hour {
|
|
return fmt.Sprintf("%dh", inter/time.Hour)
|
|
}
|
|
|
|
if inter >= time.Minute {
|
|
return fmt.Sprintf("%dm", inter/time.Minute)
|
|
}
|
|
|
|
if inter >= time.Second {
|
|
return fmt.Sprintf("%ds", inter/time.Second)
|
|
}
|
|
|
|
if inter >= time.Millisecond {
|
|
return fmt.Sprintf("%dms", inter/time.Millisecond)
|
|
}
|
|
|
|
return "1ms"
|
|
}
|
|
|
|
//nolint: gocyclo
|
|
func roundInterval(interval time.Duration) time.Duration {
|
|
switch {
|
|
// 0.015s
|
|
case interval <= 15*time.Millisecond:
|
|
return time.Millisecond * 10 // 0.01s
|
|
// 0.035s
|
|
case interval <= 35*time.Millisecond:
|
|
return time.Millisecond * 20 // 0.02s
|
|
// 0.075s
|
|
case interval <= 75*time.Millisecond:
|
|
return time.Millisecond * 50 // 0.05s
|
|
// 0.15s
|
|
case interval <= 150*time.Millisecond:
|
|
return time.Millisecond * 100 // 0.1s
|
|
// 0.35s
|
|
case interval <= 350*time.Millisecond:
|
|
return time.Millisecond * 200 // 0.2s
|
|
// 0.75s
|
|
case interval <= 750*time.Millisecond:
|
|
return time.Millisecond * 500 // 0.5s
|
|
// 1.5s
|
|
case interval <= 1500*time.Millisecond:
|
|
return time.Millisecond * 1000 // 1s
|
|
// 3.5s
|
|
case interval <= 3500*time.Millisecond:
|
|
return time.Millisecond * 2000 // 2s
|
|
// 7.5s
|
|
case interval <= 7500*time.Millisecond:
|
|
return time.Millisecond * 5000 // 5s
|
|
// 12.5s
|
|
case interval <= 12500*time.Millisecond:
|
|
return time.Millisecond * 10000 // 10s
|
|
// 17.5s
|
|
case interval <= 17500*time.Millisecond:
|
|
return time.Millisecond * 15000 // 15s
|
|
// 25s
|
|
case interval <= 25000*time.Millisecond:
|
|
return time.Millisecond * 20000 // 20s
|
|
// 45s
|
|
case interval <= 45000*time.Millisecond:
|
|
return time.Millisecond * 30000 // 30s
|
|
// 1.5m
|
|
case interval <= 90000*time.Millisecond:
|
|
return time.Millisecond * 60000 // 1m
|
|
// 3.5m
|
|
case interval <= 210000*time.Millisecond:
|
|
return time.Millisecond * 120000 // 2m
|
|
// 7.5m
|
|
case interval <= 450000*time.Millisecond:
|
|
return time.Millisecond * 300000 // 5m
|
|
// 12.5m
|
|
case interval <= 750000*time.Millisecond:
|
|
return time.Millisecond * 600000 // 10m
|
|
// 12.5m
|
|
case interval <= 1050000*time.Millisecond:
|
|
return time.Millisecond * 900000 // 15m
|
|
// 25m
|
|
case interval <= 1500000*time.Millisecond:
|
|
return time.Millisecond * 1200000 // 20m
|
|
// 45m
|
|
case interval <= 2700000*time.Millisecond:
|
|
return time.Millisecond * 1800000 // 30m
|
|
// 1.5h
|
|
case interval <= 5400000*time.Millisecond:
|
|
return time.Millisecond * 3600000 // 1h
|
|
// 2.5h
|
|
case interval <= 9000000*time.Millisecond:
|
|
return time.Millisecond * 7200000 // 2h
|
|
// 4.5h
|
|
case interval <= 16200000*time.Millisecond:
|
|
return time.Millisecond * 10800000 // 3h
|
|
// 9h
|
|
case interval <= 32400000*time.Millisecond:
|
|
return time.Millisecond * 21600000 // 6h
|
|
// 24h
|
|
case interval <= 86400000*time.Millisecond:
|
|
return time.Millisecond * 43200000 // 12h
|
|
// 48h
|
|
case interval <= 172800000*time.Millisecond:
|
|
return time.Millisecond * 86400000 // 24h
|
|
// 1w
|
|
case interval <= 604800000*time.Millisecond:
|
|
return time.Millisecond * 86400000 // 24h
|
|
// 3w
|
|
case interval <= 1814400000*time.Millisecond:
|
|
return time.Millisecond * 604800000 // 1w
|
|
// 2y
|
|
case interval < 3628800000*time.Millisecond:
|
|
return time.Millisecond * 2592000000 // 30d
|
|
default:
|
|
return time.Millisecond * 31536000000 // 1y
|
|
}
|
|
}
|